home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / p / pofo / sprachen / tbasic / tbasic.asm < prev    next >
Encoding:
Assembly Source File  |  1991-08-21  |  45.7 KB  |  2,026 lines

  1. ;***************************************************************
  2. ;*
  3. ;*
  4. ;*          TINY BASIC FOR INTEL 8086
  5. ;*
  6. ;*
  7. ;*              VERSION: 1.1
  8. ;*
  9. ;*                  BY
  10. ;*
  11. ;*              MICHAEL SULLIVAN
  12. ;*                              BASED
  13. ;*                               ON
  14. ;*                       LI-CHEN WANG'S
  15. ;*
  16. ;*                    8080 TINY BASIC
  17. ;*
  18. ;*
  19. ;*                    27 JUNE 1982
  20. ;*
  21. ;*        @COPYLEFT
  22. ;*        ALL WRONGS RESERVED
  23. ;*
  24. ;*    NOTE:
  25. ;*        8080 REGISTERS HAVE BEEN MAPPED AS FOLLOWS:
  26. ;*
  27. ;*        8080        8086
  28. ;*    -------------------------------------
  29. ;*
  30. ;*        BC    <->    CX
  31. ;*        DE    <->    DX
  32. ;*        HL    <->    BX
  33. ;*
  34. ;*
  35. ;*    VERS 1.1 - SUPPORT MS-DOS INTERUPT I/O
  36. ;*           IMPROVE RND ACTION
  37. ;*           SUPPORT TIME AND DATE FROM MS-DOS
  38. ;*
  39. ;**************************************************************
  40.     ;
  41.     ;
  42.     ORG    100H    ;STANDARD MS-DOS START ADDR.
  43. START:
  44.     MOV    SP,STACK    ;SET UP STACK
  45.     MOV    DX,MSG1    ;GET SIGN-ON MSG
  46.     CALL    PRTSTG    ;SEND IT
  47.     MOV    B,[BUFFER-2],80H ;INIT CMD LINE BUFFER
  48. ;
  49. ;    MAIN
  50. ;
  51. ; THIS IS THE MAIN LOOP THAT COLLECTS THE TINY BASIC PROGRAM
  52. ; AND STORES IT IN MEMORY.
  53. ;
  54. ; AT START, IT PRINTS OUT "(CR)OK(LF)", AND INITIALIZES THE
  55. ; STACK AND SOME OTHER INTERNAL VARIABLES. THEN IT PROMPTS
  56. ; ">" AND READS A LINE. IF THE LINE STARTS WITH A NONZERO
  57. ; NUMBER, THIS NUMBER IS THE LINE NUMBER. THE LINE NUMBER
  58. ; (IN 16 BIT BINARY) AND THE REST OF THE LINE (INCLUDING
  59. ; ITS (CR))IS STORED IN MEMORY. IF A LINE WITH THE SAME
  60. ; LINE NUMBER IS ALREADY THERE, IT IS REPLACED BY THE NEW
  61. ; ONE. IF THE REST OF THE LINE CONSISTS OF A (CR) ONLY, IT
  62. ; IS STORED AND ANY EXISTING LINE WITH THE SAME LINE
  63. ; NUMBER IS DELETED.
  64. ;
  65. ; AFTER A LINE IS INSERTED, REPLACED, OR DELETED, THE
  66. ; PROGRAM LOOPS BACK AND ASKS FOR ANOTHER LINE. THIS LOOP
  67. ; WILL BE TERMINATED WHEN IT READS A LINE WITH ZERO OR NO
  68. ; LINE NUMBER: CONTROL IS THEN TRANSFERED TO "DIRECT".
  69. ;
  70. ; THE TINY BASIC PROGRAM SAVE AREA STARTS AT THE MEMORY
  71. ; LOCATION LABELED "TXTBGN" AND ENDS AT "TXTEND". WE ALWAYS
  72. ; FILL THIS AREA STARTING AT "TXTBGN", THE UNFILLED PORTION
  73. ; POINTED TO BY THE CONTENTS OF THE MEMORY LOCATION LABELED
  74. ; "TXTUNF".
  75. ;
  76. ; THE MEMORY LOCATION "CURRNT" POINTS TO THE LINE NUMBER
  77. ; THAT IS CURRENTLY BEING INTERPRETED. WHILE WE AR IN THIS
  78. ; LOOP OR WHILE WE ARE INTERPRETING A DIRECT COMMAND
  79. ; (SEE NEXT SECTION), "CURRNT" SHOULD POINT TO A 0.
  80. ;
  81. RSTART:
  82.     MOV    SP,STACK    ;SET STACK POINTER
  83. ST1:
  84.     CALL    CRLF
  85.     MOV    DX,OK    ;DE->STRING
  86.     SUB    AL,AL
  87.     CALL    PRTSTG    ;PRINT PROMPT
  88.     MOV    W,[CURRNT],0 ;CURRENT LINE # = 0
  89. ST2:
  90.     MOV    W,[LOPVAR],0
  91.     MOV    W,[STKGOS],0
  92. ST3:
  93.     MOV    AL,'>'    ;PROMPT ">" NOW
  94.     CALL    GETLN    ;READ A LINE
  95.     PUSH    DI    ;DI -> END OF LINE
  96. ST3A:
  97.     MOV    DX,BUFFER ;DX -> BEGINNING OF LINE
  98.     CALL    TSTNUM    ;TEST IF IT'S A NUMBER
  99.     MOV    AH,0
  100.     CALL    IGNBLNK
  101.     OR    BX,BX    ;BX:= VALUE OF # OR 0 IF NO # FOUND
  102.     POP    CX    ;CX -> END OF LINE
  103.     JNZ    ST3B
  104.     JMP    DIRECT
  105. ST3B:
  106.     DEC    DX
  107.     DEC    DX
  108.     MOV    AX,BX    ;GET LINE #
  109.     MOV    DI,DX
  110.     STOW        ;VALUE OF LINE # THERE
  111.     PUSH    CX
  112.     PUSH    DX    ;BX,DX -> BEGIN,END
  113.     MOV    AX,CX
  114.     SUB    AX,DX
  115.     PUSH    AX    ;AX:= # BYTES IN LINE
  116.     CALL    FNDLN    ;FIND THIS LINE IN SAVE
  117.     PUSH    DX    ;AREA, DX -> SAVE AREA
  118.     JNZ    ST4    ;NZ:NOT FOUND, INSERT
  119.     PUSH    DX    ;Z:FOUND, DELERE IT
  120.     CALL    FNDNXT    ;FIND NEXT LINE
  121.             ;DE -> NEXT LIE
  122.     POP    CX    ;CX -> LINE TO BE DELETED
  123.     MOV    BX,[TXTUNF] ;BX -> UNFILLED SAVE AREA
  124.     CALL    MVUP    ;MOVE UP TO DELETE
  125.     MOV    BX,CX    ;TXTUNF -> UNFILLED AREA
  126.     MOV    [TXTUNF],BX ;UPDATE
  127. ST4:
  128.     POP    CX    ;GET READY TO INSERT
  129.     MOV    BX,[TXTUNF] ;BUT FIRST CHECK IF
  130.     POP    AX    ;AX = # CHARS IN LINE
  131.     PUSH    BX    ;IS 3 (LINE # AND CR)
  132.     CMP    AL,3    ;THEN DO NOT INSERT
  133.     JZ    RSTART    ;MUST CLEAR THE STACK
  134.     ADD    AX,BX    ;COMPUTE NEW TSTUNF
  135.     MOV    BX,AX    ;BX -> NEW UNFILLED AREA
  136. ST4A:
  137.     MOV    DX,TXTEND ;CHECK TO SEE IF THERE
  138.     CMP    BX,DX    ;IS ENOUGH SPACE
  139.     JC    ST4B    ;SORRY, NO ROOM FOR IT
  140.     JMP    QSORRY
  141. ST4B:
  142.     MOV    [TXTUNF],BX ;OK, UPDATE TXTUNF
  143.     POP    DX    ;DX -> OLD UNFILLED AREA
  144.     CALL    MVDOWN
  145.     POP    DX    ;DX -> BEGIN, BX -> END
  146.     POP    BX
  147.     CALL    MVUP    ;MOVE NEW LINE TO SAVE AREA
  148.     JP    ST3
  149.     
  150. TSTV:    MOV    AH,64    ;TEST VARIABLES
  151.     CALL    IGNBLNK
  152.     JC    RET
  153. TSTV1:
  154.     JNZ    TV1    ;NOT @ ARRAY
  155.     CALL    PARN    ;@ SHOULD BE FOLLOWED
  156.     ADD    BX,BX
  157.     JNC    SS1B    ;IS INDEX TOO BIG?
  158.         JMP     QHOW
  159. SS1B:    PUSH    DX    ;WILL IT OVERWRITE
  160.     XCHG    DX,BX    ;TEXT?
  161.     CALL    SIZE    ;FIND SIZE OF FREE
  162.     CMP    BX,DX    ;AND CHECK THAT
  163.     JNC    SS1A    ;IFF SO, SAY "SORRY"
  164.         JMP     ASORRY
  165. SS1A:
  166.     MOV    BX,VARBGN    ;IFF NOT, GET ADDRESS
  167.     SUB    BX,DX    ;OF @(EXPR) AND PUT IT
  168.     POP    DX    ;IN HL
  169.     RET    ;C FLAG IS CLEARED
  170. TV1:
  171.     CMP    AL,27    ;NOT @, IS IT A TO Z?
  172. CMC:
  173.     ;IFF NOT, RETURN C FLAG
  174.     JC    RET    ;IFF NOT, RETURN C FLAG
  175.     INC    DX
  176. TV1A:
  177.     MOV    BX,VARBGN    ;COMPUTE ADDRESS OF
  178.     MOV    AH,0    ;CLEAR UPPER BYTE
  179.     ADD    AX,AX    ;AX:=AX*2 (WORD STORAGE)
  180.     ADD    BX,AX    ;BX:=VARBGN+2*AL
  181.     RET        ;USE CARRY AS ERROR INDICATOR
  182. ;
  183. ; TSTNUM - AT ENTRY DX -> BUFFER OF ASCII CHARACTERS
  184. ;
  185. TSTNUM:
  186.     MOV    BX,0    ;****TSTNUM****
  187.     MOV    CH,BH    ;TEST IFF THE TEXT IS
  188.     MOV    AH,0    ;FOR CMP IN IGNBLNK
  189.     CALL    IGNBLNK    ;A NUMBER.
  190. TN1:
  191.     CMP    AL,'0'    ;IFF NOT, RETURN 0 IN
  192.     JC    RET    ;B AND HL
  193.     CMP    AL,':'    ;IFF NUMBERS, CONVERT
  194.     JNC    RET    ;TO BINARY IN BX AND
  195.     MOV    AL,0F0H        ;SET AL TO # OF DIGITS
  196.     AND    AL,BH    ;IFF BH>255, THERE IS NO
  197.     JNZ    QHOW    ;ROOM FOR NEXT DIGIT
  198.     INC    CH    ;CH COUNTS NUMBER OF DIGITS
  199.     PUSH    CX
  200.     MOV    AX,BX    ;BX:=10*BX+(NEW DIGIT)
  201.         MOV     CX,10
  202.     PUSH    DX    ;SAVE DX
  203.         MUL     AX,CX
  204.         MOV     BX,AX   ;PARTIAL RESULT NOW IN BX
  205.     POP    DX    ;RESTORE
  206.     MOV    SI,DX
  207.     LODB            ;ASCII DIGIT IN AL NOW
  208.         SUB     AL,48   ;CONVERT TO BINARY
  209.         MOV     AH,0
  210.         ADD     BX,AX   ;FULL RESULT NOW IN BX
  211.     POP    CX
  212.     LODB            ;REPEAT FOR MORE DIGITS
  213.     LAHF        ;SAVE FLAGS
  214.     INC    DX
  215.     SAHF        ;RESTORE FLAGS
  216.     JNS    TN1    ;QUIT IF NO NUM OR OVERFLOW
  217. QHOW:
  218.     PUSH    DX    ;****ERROR: "HOW?"****
  219. AHOW:
  220.     MOV    DX,HOW
  221.     JMP    ERROR
  222. HOW:
  223.     DB    'HOW?',0DH
  224. OK:
  225.     DB    'OK',0DH
  226. WHAT:
  227.     DB    'WHAT?',0DH
  228. SORRY:
  229.     DB    'SORRY',0DH
  230. ;
  231. ;*
  232. ;**********************************************************
  233. ;*
  234. ;* *** TABLES *** DIRECT *** & EXEC ***
  235. ;*
  236. ;* THIS SECTION OF THE CODE TESTS A STRING AGAINST A TABLE.
  237. ;* WHEN A MATCH IS FOUND, CONTROL IS TRANSFERRED TO THE SECTION
  238. ;* OF CODE ACCORDING TO THE TABLE.
  239. ;*
  240. ;* AT 'EXEC' DX SHOULD POINT TO THE STRING AND BX SHOULD POINT
  241. ;* TO THE TABLE-1. AT 'DIRECT', DX SHOULD POINT TO THE STRING,
  242. ;* BX WILL BE SET UP TO POINT TO TAB1-1, WHICH IS THE TABLE OF
  243. ;* ALL DIRECT AND STATEMENT COMMANDS.
  244. ;*
  245. ;* A '.' IN THE STRING WILL TERMINATE THE TEST AND THE PARTIAL
  246. ;* MATCH WILL BE CONSIDERED AS A MATCH. E.G., 'PR.',
  247. ;* 'PRI.', 'PRIN.', OR 'PRINT' WILL ALL MATCH 'PRINT'.
  248. ;*
  249. ;* THE TABLE CONSISTS OF ANY NUMBER OF ITEMS. EACH ITEM
  250. ;* IS A STRING OF CHARACTERS WITH BIT 7 SET TO 1 IN LAST CHAR
  251. ;* A JUMP ADDRESS IS STORED FOLLOWING EACH CHARACTER ENTRY.
  252. ;*
  253. ;* END OF TABLE IS AN ITEM WITH A JUMP ADDRESS ONLY. IF THE 
  254. ;* STRING DOES NOT MATCH ANY OF THE OTHER ITEMS, IT WILL
  255. ;* MATCH THIS NULL ITEM AS DEFAULT. THE DEFAULT IS INDICATED
  256. ;* BY FOLLOWING THE 80H DEFAULT INDICATOR.
  257. ;*
  258.  
  259. TAB1:   EQU    $    ;DIRECT COMMANDS
  260.     DM    'LIST'
  261.     DW    LIST    ;EXECUTION ADDRESSES
  262.     DM    'EDIT'
  263.     DW    EDIT
  264.     DM    'E'
  265.     DW    EDIT    ;HAVE SHORT FORM DEFINED ALSO
  266.     DM    'RUN'
  267.     DW    RUN
  268.     DM    'NEW'
  269.     DW    NEW
  270.     DM    'LOAD'
  271.     DW    DLOAD
  272.     DM    'SAVE'
  273.     DW    DSAVE
  274.     DM    'BYE'    ;GO BACK TO DOS (EXIT TBASIC)
  275.     DW    BYE
  276. TAB2:    EQU    $    ;DIRECT/STATEMENT
  277.     DM    'NEXT'
  278.     DW    NEXT    ;EXECUTION ADDRESSES
  279.     DM    'LET'
  280.     DW    LET
  281.     DM    'OUT'
  282.     DW    OUTCMD
  283.     DM    'POKE'
  284.     DW    POKE
  285.     DM    'WAIT'
  286.     DW    WAITCM
  287.     DM    'IF'
  288.     DW    IFF
  289.     DM    'GOTO'
  290.     DW    GOTO
  291.     DM    'GOSUB'
  292.     DW    GOSUB
  293.     DM    'RETURN'
  294.     DW    RETURN
  295.     DM    'REM'
  296.     DW    REM
  297.     DM    'FOR'
  298.     DW    FOR
  299.     DM    'INPUT'
  300.     DW    INPUT
  301.     DM    'PRINT'
  302.     DW    PRINT
  303.     DM    'STOP'
  304.     DW    STOP
  305.     DB    128    ;SIGNALS END
  306.             ;REMEMBER TO MOVE DEFAULT DOWN.
  307.     DW    DEFLT    ;LAST POSIBILITY
  308. TAB4:    EQU    $    ;FUNCTIONS
  309.     DM    'RND'
  310.     DW    RND
  311.     DM    'INP'
  312.     DW    INP
  313.     DM    'PEEK'
  314.     DW    PEEK
  315.     DM    'USR'
  316.     DW    USR
  317.     DM    'ABS'
  318.     DW    ABS
  319.     DM    'SIZE'
  320.     DW    SIZE
  321.     DB    128    ;SIGNALS END
  322.             ;YOU CAN ADD MORE FUNCTIONS BUT REMEMBER
  323.             ;TO MOVE XP40 DOWN
  324.     DW    XP40
  325. TAB5:    EQU    $    ;"TO" IN "FOR"
  326.     DM    'TO'
  327. TAB5A:    DW    FR1
  328.     DB    128
  329.     DW    QWHAT
  330. TAB6:    EQU    $    ;"STEP" IN "FOR"
  331.     DM    'STEP'
  332. TAB6A:    DW    FR2
  333.     DB    128
  334.     DW    FR3
  335. TAB8:    EQU    $    ;RELATION OPERATORS
  336.     DM    '>='
  337.     DW    XP11    ;EXECUTION ADDRESS
  338.     DM    '#'
  339.     DW    XP12
  340.     DM    '>'
  341.     DW    XP13
  342.     DM    '='
  343.     DW    XP15
  344.     DM    '<='
  345.     DW    XP14
  346.     DM    '<'
  347.     DW    XP16
  348.     DB    128
  349.     DW    XP17
  350. ;
  351. ; END OF PARSER ACTION TABLE
  352. ;
  353. ;
  354. ; AT ENTRY BX -> COMMAND TABLE (ABOVE)
  355. ;       DX -> COMMAND LINE (I.E. "BUFFER")
  356. ;
  357. DIRECT:
  358.     MOV    BX,TAB1-1    ;***DIRECT***
  359.     ;*
  360. EXEC:    EQU    $    ;***EXEC***
  361. EX0:
  362.     MOV    AH,0
  363.     CALL    IGNBLNK    ;IGNORE LEADING BLANKS
  364.     PUSH    DX    ;SAVE POINTER
  365.     MOV    SI,DX
  366. EX1:    LODB        ;GET CHAR WHERE DX ->
  367.     INC    DX    ;PRESERVE POINTER
  368.     CMP    AL,'.'    ;WE DECLARE A MATCH
  369.     JZ    EX4
  370.     INC    BX
  371.     MOV    AH,[BX]
  372.     AND    AH,127    ;STRIP BIT 7
  373.     CMP    AL,AH    ;COMPARISON NOW EASY
  374.     JZ    EX2
  375.     ; NO MATCH - CHECK NEXT ENTRY
  376. EX0A:    CMP    B,[BX],128    ;BYTE COMPARE
  377.     JNC    EX0B
  378.     INC    BX
  379.     JP    EX0A
  380.     ; AT THIS POINT HAVE LAST LETTER
  381. EX0B:    ADD    BX,3    ;GET PAST EXECUTION ADDRESS
  382.     CMP    B,[BX],128    ;FOUND DEFAULT?
  383.     JZ    EX3A    ;IF SO, EXECUTE DEFAULT
  384.     DEC    BX    ;CORRECT FOR PRE-INCREMENT
  385.     POP    DX    ;RESTORE POINTER
  386.     JP    EX0    ;LOOK SOME MORE FOR A MATCH
  387. EX4:    INC    BX
  388.     CMP    B,[BX],128
  389.     JC    EX4
  390.     JP    EX3
  391. ;
  392. EX3A:    DEC    SI
  393.     JP    EX3    ;CORRECT SI FOR DEFAULT EXECUTION
  394. EX2:    CMP    B,[BX],128    ;END OF RESERVED WORD?
  395.     JC    EX1    ;NO - CHECK SOME MORE
  396.     ; AT THIS POINT NEED TO GET EXECUTION ADDRESS
  397.  
  398. EX3:    INC    BX    ;BX -> EXECUTION ADDRESS
  399.     POP    AX    ;CLEAR STACK
  400.     MOV    DX,SI    ;RESET POINTER
  401.     JMP    [BX]    ;DO IT
  402. ;*
  403. ;
  404. ;
  405. ; WHAT FOLLOWS IS THE CODE TO ECECUTE DIRECT AND STATEMENT COM-
  406. ; MANDS. CONTROL IS TRANSFERED TO THESE POINTS VIA THE  COMMAND
  407. ; TABLE LOOKUP CODE OF 'DIRECT' AND 'EXEC' IN THE LAST SECTION.
  408. ; AFTER THE COMMAND IS EXECUTED,  CONTROL  IS  TRANSFERRED   TO
  409. ; OTHER SECTIONS AS FOLLOWS:
  410. ;
  411. ; FOR 'LIST','NEW', ANS 'STOP': GO BACK TO 'RSTART'
  412. ;
  413. ; FOR 'RUN',: GO EXECUTE THE FIRST STORED LINE IFF ANY; ELSE
  414. ;            GO BACK TO RSTART.
  415. ;
  416. ; FOR 'GOTO' AND 'GOSUB': GO EXECUTE THE TARGET LINE.
  417. ;
  418. ; FOR 'RETURN' AND 'NEXT': GO BACK TO SAVED RETURN LINE.
  419. ;
  420. ; FOR ALL OTHERS: IFF 'CURRNT' -> 0, GO TO 'RSTART', ELSE
  421. ;            GO EXECUTE NEXT COMMAND. (THIS IS DONE
  422. ;            IN 'FINISH'.)
  423. ;
  424. ;
  425. ; ****NEW****STOP****RUN (& FRIENDS)****GOTO****
  426. ;
  427. ; 'NEW(CR)' SETS 'TXTUNF' TO POINT TO 'TXTBGN'
  428. ;
  429. ; 'STOP(CR)' GOES BACK TO 'RSTART'
  430. ;
  431. ; 'RUN(CR)' FINDS THE FIRST STROED LINE, STORES ITS ADDRESS
  432. ;    (IN 'CURRNT'), AND START TO EXECUTE IT. NOTE THAT ONLY
  433. ;    THOSE COMMANDS IN TAB2 ARE LEGAL FOR STORED PROGRAMS.
  434. ;
  435. ; THERE ARE THREE MORE ENTRIES IN 'RUN':
  436. ;
  437. ;    'RUNNXL' FINDS NEXT LINE, STORES ITS ADDR AND EXEC IT.
  438. ;    'RUNTSL' STORES THE ADDRESS OF THIS LINE AND EXECUTES IT
  439. ;    'RUNSML' CONTINUES THE EXECUTION ON SAME LINE.
  440. ;
  441. ; 'GOTO(EXPR)' EVALUATES THE EXPRESSION, FINDS THE TARGET LINE,
  442. ;    AND JUMPS TO 'RUNTSL' TO DO IT.
  443. ;
  444. ; 'DLOAD' LOADS A NAMES PROGRAM FROM DISK (ANYNAME.TBI)
  445. ;
  446. ; 'DSAVE' SAVES A NAMES PROGRAM ON DISK
  447. ;
  448. ; 'FCBSET' SETS UP THE MSDOS FILE CONTROL BLOCK FOR SUBSEQUENT
  449. ;    DISK I/O.
  450. ;
  451. ;
  452. NEW:
  453.     MOV    W,[TXTUNF],TXTBGN
  454.     ;
  455. STOP:
  456.     CALL    ENDCHK    ;****STOP(CR)****
  457.     JMP    RSTART
  458.     ;
  459. RUN:
  460.     CALL    ENDCHK    ;****RUN(CR)****
  461.     MOV    DX,TXTBGN    ;FIRST SAVED LINE
  462.     ;
  463. RUNNXL:
  464.     MOV    BX,0    ;****RUNNXL****
  465.     CALL    FNDLNP    ;FIND WHATEVER LINE
  466.     JNC    RUNTSL    ;C: PASSED TXTUNF, QUIT
  467.         JMP     RSTART
  468.     ;
  469. RUNTSL:
  470.     XCHG    DX,BX    ;****RUNTSL****
  471.     MOV    [CURRNT],BX    ;SET 'CURRNT"->LINE #
  472.     XCHG    DX,BX
  473.     INC    DX
  474.     INC    DX
  475.     ;
  476. RUNSML:
  477.     CALL    CHKIO    ;****RUNSML****
  478.     MOV    BX,TAB2-1    ;FIND COMMAND IN TABLE 2
  479.     JMP    EXEC    ;AND EXECUTE IT
  480.     ;
  481. GOTO:
  482.     CALL    EXP    ;****GOTO(EXPR)****
  483.     PUSH    DX    ;SAVE FOR ERROR ROUTINE
  484.     CALL    ENDCHK    ;MUST FIND A 0DH (CR)
  485.     CALL    FNDLN    ;FIND THE TARGET LINE
  486.     JZ    GT1    ;NO SUCH LINE #
  487.         JMP     AHOW
  488. GT1:    POP    AX
  489.     JP    RUNTSL    ;GO DO IT
  490.     ;
  491.     ; BDOS EQUATES (FOR MS-DOS)
  492.     ;
  493. BYE:    EQU    0    ;BDOS EXIT ADDRESS
  494. FCB:    EQU    5CH
  495. SETDMA:    EQU    26
  496. OPEN:    EQU    15
  497. READD:    EQU    20
  498. WRITED:    EQU    21
  499. CLOSE:    EQU    16
  500. MAKE:    EQU    22
  501. BCONIN:    EQU    10    ;BUFFERED CONSOLE INPUT
  502. DELETE:    EQU    19
  503. CONOUT:    EQU    2    ;CONSOLE OUTPUT
  504. CONST:    EQU    11    ;CONSOLE STATUS
  505.     ;
  506.     ;
  507. DLOAD:
  508.     MOV    AH,0
  509.     CALL    IGNBLNK    ;IGNORE BLANKS
  510.     PUSH    BX    ;SAVE H
  511.     CALL    FCBSET    ;SET UP FILE CONTROL BLOCK
  512.     PUSH    DX    ;SAVE THE REST
  513.     PUSH    CX    ;SAVE THE REST
  514.     MOV    DX,FCB    ;GET FCB ADDR
  515.     MOV    AH,OPEN    ;PREPARE TO OPEN FILE
  516.     INT    33    ;CALL MS-DOS TO OPEN FILE
  517.     CMP    AL,0FFH    ;IS IT THERE?
  518.     JNZ    DL1    ;NO, SEND ERROR
  519.         JMP     QHOW
  520. DL1:    XOR    AL,AL    ;CLEAR A
  521.     MOV    [FCB+32],AL    ;START AT RECORD 0
  522.     MOV    DX,TXTBGN    ;GET BEGINNING
  523. LOAD:
  524.     PUSH    DX    ;SAVE DMA ADDRESS
  525.     MOV    AH,SETDMA
  526.     INT    33    ;CALL MS-DOS TO SET DAM ADDR
  527.     MOV    AH,READD
  528.     MOV    DX,FCB
  529.     INT    33    ;CALL MS-DOS TO READ SECTOR
  530.     CMP    AL,1    ;DONE?
  531.     JC    RDMORE    ;NO, READ MORE
  532.     JZ    LL1
  533. LOAD1:    JMP    QHOW    ;BAD READ OR NO DELIMITER
  534. LL1:    MOV    AH,CLOSE
  535.     MOV    DX,FCB
  536.     INT    33    ;CALL MS-DOS TO CLOSE FILE
  537.     POP    BP    ;DMA ADDR IN BP
  538.     SUB    BP,100H ;BACKUP
  539.     MOV    CX,100H ;MAX LOOPS
  540. RDM1:    INC    BP    ;PRE INC
  541.     CMP    W,[BP],0 ;FOUND DELIMITER?
  542.     LOOPNZ    RDM1    ;KEEP LOOKING
  543.     CMP    CL,0    ;MAC LOOPS EXECUTED?
  544.     JZ    LOAD1    ;GIVE ERROR IF SO
  545.     MOV    [TXTUNF],BP ;UPDATE POINTER
  546.     POP    CX    ;GET OLD REG BACK
  547.     POP    DX    ;GET OLD REG BACK
  548.     POP    BX    ;GET OLD REG BACK
  549.     CALL    FINISH    ;FINISH
  550. RDMORE:
  551.     POP    DX    ;GET DMA ADDR
  552.     MOV    BX,80H    ;GET 128
  553.     ADD    BX,DX    ;ADD IT TO DMA ADDR
  554.     XCHG    DX,BX    ;BACK IN D
  555.     JMP    LOAD    ;AND READ SOME MORE
  556.     ;
  557. DSAVE:
  558.     CMP    W,[TXTUNF],TXTBGN ;SEE IF ANYTHING TO SAVE
  559.     JNZ    DS1A
  560.     JMP    QWHAT
  561. DS1A:
  562.     MOV    BP,[TXTUNF]
  563.     MOV    W,[BP],0 ;SET DELIMITER
  564.     MOV    AH,0
  565.     CALL    IGNBLNK    ;IGNORE BLANKS
  566.     PUSH    BX    ;SAVE BX
  567.     CALL    FCBSET    ;SETUP FCB
  568.     PUSH    DX
  569.     PUSH    CX    ;SAVE OTHERS
  570.     MOV    DX,FCB
  571.     MOV    AH,DELETE
  572.     INT    33    ;CALL MS-DOS TO ERASE FILE
  573.     MOV    DX,FCB
  574.     MOV    AH,MAKE
  575.     INT    33    ;CALL MS-DOS TO MAKE A NEW ONE
  576.     CMP    AL,0FFH    ;IS THERE SPACE?
  577.     JNZ    DS1
  578.         JMP     QHOW    ;NO, ERROR
  579. DS1:    XOR    AL,AL    ;CLEAR A
  580.     MOV    [FCB+32],AL    ;START AT RECORD 0
  581.     MOV    DX,TXTBGN    ;GET BEGINNING
  582. SAVE:
  583.     PUSH    DX    ;SAVE DMA ADDR
  584.     MOV    AH,SETDMA
  585.     INT    33    ;CALL MS-DOS TO SET DMA ADDR
  586.     MOV    AH,WRITED
  587.     MOV    DX,FCB
  588.     INT    33    ;CALL MS-DOS TO WRITE SECTOR
  589.     OR    AL,AL    ;SET FLAGS
  590.     JZ    SS1    ;IF NOT ZERO, ERROR
  591.         JMP     QHOW
  592. SS1:    POP    DX    ;GET DMA ADDR BACK
  593.     MOV    AX,DX
  594.     CMP    AX,[TXTUNF]    ;SEE IF DONE
  595.     JZ    SAVDON
  596.     JNC    SAVDON    ;JUMP IF DONE
  597. WRITMOR:
  598.     MOV    BX,80H
  599.     ADD    BX,DX
  600.     XCHG    DX,BX    ;GET IT TO D
  601.     JP    SAVE
  602. SAVDON:
  603.     MOV    AH,CLOSE
  604.     MOV    DX,FCB
  605.     INT    33    ;CALL MS-DOS TO CLOSE FILE
  606.     POP    CX    ;GET REGS BACK
  607.     POP    DX    ;GET REGS BACK
  608.     POP    BX    ;GET REGS BACK
  609.     CALL    FINISH
  610.     ;
  611. FCBSET:
  612.     MOV    BX,FCB    ;GET FCB ADDR
  613.     MOV    B,[BX],0    ;CLEAR ENTRY TYPE
  614. FNCLR:
  615.     INC    BX
  616.     MOV    B,[BX],' '    ;CLEAR TO SPACE
  617.     MOV    AX,FCB+8
  618.     CMP    AX,BX    ;DONE?
  619.     JNZ    FNCLR    ;NO, DO IT AGAIN
  620.     INC    BX
  621.     MOV    B,[BX],'T'    ;SET FILE TYPE TO 'TBI'
  622.     INC    BX
  623.     MOV    B,[BX],'B'
  624.     INC    BX
  625.     MOV    B,[BX],'I'
  626. EXRC:
  627.     INC    BX
  628.     MOV    B,[BX],0
  629.     MOV    AX,FCB+15
  630.     CMP    AX,BX
  631.     JNZ    EXRC    ;NO, CONTINUE
  632.     MOV    BX,FCB+1    ;GET FILENAME START
  633. FN:
  634.     MOV    SI,DX
  635.     LODB    ;GET CHAR
  636.     CMP    AL,0DH    ;IS IT A 'CR'
  637.     JZ    RET    ;YES, DONE
  638.     CMP    AL,'!'    ;LEGAL CHAR?
  639.     JNC     FN1    ;NO, SEND ERROR
  640.         JMP     QWHAT
  641. FN1:    CMP    AL,'['    ;AGAIN
  642.     JC    FN2    ;DITTO
  643.         JMP     QWHAT
  644. FN2:    MOV    [BX],AL    ;SAVE IT IN FCB
  645.     INC    BX
  646.     INC    DX
  647.     MOV    AX,FCB+9
  648.     CMP    AX,BX    ;LAST?
  649.     JNZ    FN    ;NO, CONTINUE
  650.     RET    ;TRUNCATE AT EIGHT CHARS
  651. ;
  652. ;
  653. ; ****LIST**** AND ****PRINT**** AND ****EDIT****
  654. ;
  655. ; LIST HAS TWO FORMS:
  656. ;    'LIST(CR)' LISTS ALL SAVED LINES
  657. ;    'LIST #(CR)' START LIST AT THIS LINE #
  658. ; YOU CAN STOP LISTING BY CONTROL C KEY
  659. ;
  660. ; PRINT COMMAND IS 'PRINT ....;' OR 'PRINT ....(CR)'
  661. ; WHERE '....' IS A LIST OF EXPRESIONS, FORMATS, BACKARROWS, AND
  662. ; STRINGS. THESE ITEMS ARE SEPERATED BY COMMAS.
  663. ;
  664. ; A FORMAT IS A POUND SIGN FOLLOWED BY A NUMBER. IT CONTROLS THE
  665. ; NUMBER OF SPACES THE VALUE OF AN EXPRESSION IS TO BE PRINTED.
  666. ; TED. IT STAYS EFFECTIVE FOR THE REST OF THE PRINT, UNLESS
  667. ; CHANGED BY ANOTHER FORMAT. IF NO FORMAT SPEC, 6 POSITIONS
  668. ; WILL BE USED.
  669. ;
  670. ; A STRING IS QUOTED IN A PAIR OF SINGLE QUOTES OR DOUBLE
  671. ; QUOTES.
  672. ;
  673. ; A BACK-ARROW MEANS GENERATE A (CR) WITHOUT (LF).
  674. ;
  675. ; A (CRLF) IS GENERATED AFTER THE ENTIRE LIST HAS BEEN PRINT OR
  676. ; IF THE LIST IS A NULL LIST. HOWEVER IF THE LIST ENDED WITH A 
  677. ; COMMA, NO (CR) IS GENERATED.
  678. ;
  679. ;
  680. LIST:
  681.     CALL    TSTNUM    ;TEST IFF THERE IS A #
  682.     CALL    ENDCHK    ;IFF NO # WE GET A 0
  683.     CALL    FNDLN    ;FIND THIS OR NEXT LINE
  684. LS1:
  685.     JNC    LS2    ;C: PASSED TXTUNF
  686.         JMP     RSTART
  687. LS2:    CALL    PRTLN    ;PRINT THE LINE
  688.     CALL    CHKIO    ;SEE IF ^X OR ^C
  689.     CALL    FNDLNP    ;FIND NEXT LINE
  690.     JP    LS1    ;LOOP BACK
  691.     ;
  692. ;
  693. EDIT:
  694.     CALL    TSTNUM    ;TEST IF THERE IS A #
  695.     CALL    ENDCHK    ;AT END?
  696.     CALL    FNDLN    ;FIND SPEC LINE OR NEXT LINE
  697.     PUSH    DX    ;SAVE LINE #
  698.     JNC    ED2    ;C: PASSED TXTUNF
  699.     POP    DX    ;THROW AWAY LINE #
  700. ED1:    JMP    RSTART
  701. ED2:
  702.     CALL    PRTLN    ;PRINT THE LINE
  703.     POP    DX    ;GET LINE # BACK
  704.     MOV    B,[OCSW],0 ;DIRECT OUTPUT TO BUFFER
  705.     MOV    B,[BUFFER-1],0 ;CLEAR CHAR COUNT
  706.     MOV    B,[PRTLN1+1],4 ;PRINT ONE LESS SPACE
  707.     MOV    DI,BUFFER ;PREPARE TO MOVE
  708.     CALL    PRTLN
  709.     MOV    B,[OCSW],0FFH ;REDIRECT OUTPUT TO CONSOLE
  710.     DEC    [BUFFER-1] ;AVOID CR?
  711.     MOV    B,[PRTLN1+1],5 ;RESTORE PRTLN
  712.     JMP    ST3    ;PROMPT AND GETLINE ONLY
  713. PRINT:
  714.     MOV    CL,6    ;C:= # OF SPACES
  715.     MOV    AH,';'    ;CHECK FOR ';' IN IGNBLNK
  716.     CALL    IGNBLNK    ;IGNORE BLANKS
  717.     JNZ    PR2    ;JUMP IF ';' NOT FOUND
  718.     CALL    CRLF    ;GIVE CR,LF AND
  719.     JMP    RUNSML    ;CONTINUE SAME LINE
  720. PR2:
  721.     MOV    AH,0DH
  722.     CALL    IGNBLNK
  723.     JNZ    PR0
  724.     CALL    CRLF    ;ALSO GIVE CRLF AND
  725.     JMP    RUNNXL    ;GOTO NEXT LINE
  726. PR0:
  727.     MOV    AH,'#'
  728.     CALL    IGNBLNK
  729.     JNZ    PR1
  730.     CALL    EXP    ;YES, EVALUATE EXPR
  731.     MOV    CL,BL    ;AND SAVE IT IN C
  732.     JP     PR3    ;LOOK FOR MORE TO PRINT
  733. PR1:
  734.     CALL    QTSTG    ;OR IS IT A STRING?
  735.     JP    PR8    ;IFF NOT, MUST BE EXPRESSION
  736. PR3:
  737.     MOV    AH,','
  738.     CALL    IGNBLNK
  739.     JNZ    PR6
  740.     CALL    FIN    ;IN THE LIST
  741.     JP    PR0    ;LIST CONTINUES
  742. PR6:
  743.     CALL    CRLF    ;LIST ENDS
  744.     CALL    FINISH
  745. PR8:
  746.     CALL    EXP    ;EVAL THE EXPR
  747.     PUSH    CX
  748.     CALL    PRTNUM    ;PRINT THE VALUE
  749.     POP    CX
  750.     JP    PR3    ;MORE TO PRINT?
  751. ;
  752. ;
  753. ; ****GOSUB**** AND ****RETURN****
  754. ;
  755. ; 'GOSUB (EXPR);' OR 'GOSUB EXPR(CR)' IS LIKE THE 'GOTO' COMMAND
  756. ; EXCEPT THAT THE CURRENT TEXT POINTER, STACK POINTER ETC.   ARE
  757. ; SAVED SO THAT EXECUTION CAN BE CONTINUED AFTER THE  SUBROUTINE
  758. ; 'RETURN'. IN ORDER THAT 'GOSUB' CAN BE NESTED (AND EVEN RECUR-
  759. ; SIVE), THE SAVE AREA MUST BE  STACKED.  THE  STACK  POINTER IS
  760. ; SAVED IN 'STKGOS'. THE OLD 'STKGOS' IS SAVED IN THE STACK. IF
  761. ; WE ARE IN THE MAIN ROUTINE, 'STKGOS' IS ZERO (THIS WAS DONE BY
  762. ; THE "MAIN" SECTION OF THE CODE),  BUT  WE  STILL  SAVE  IT  AS
  763. ; A FLAG FOR NO FURTHER RETURNS.
  764. ;
  765. ; 'RETURN(CR)' UNDOES EVERYTHING THAT 'GOSUB' DID, AND THUS  RE-
  766. ; TURNS THE EXECUTION TO THE COMMAND AFTER THE MOST RECENT  'GO-
  767. ; SUB'. IFF 'STKGOS' IS ZERO, IT INDICATES THAT WE NEVER  HAD  A
  768. ; 'GOSUB' AND IS THUS AN ERROR.
  769. ;
  770. ;
  771. GOSUB:
  772.     CALL    PUSHA    ;SAVE THE CURRENT 'FOR'
  773.     CALL    EXP    ;PARAMETERS
  774.     PUSH    DX
  775.     CALL    FNDLN    ;FIND THE TARGET LINE
  776.     JZ    GS1    ;NOT THERE, SAY "HOW?"
  777.         JMP     AHOW
  778. GS1:    MOV    BX,[CURRNT]    ;FOUND IT, SAVE OLD
  779.     PUSH    BX    ;'CURRNT' OLD 'STKGOS'
  780.     MOV    BX,[STKGOS]
  781.     PUSH    BX
  782.     MOV    BX,0    ;AND LOAD NEW ONES
  783.     MOV    [LOPVAR],BX
  784.     ADD    BX,SP
  785.     MOV    [STKGOS],BX
  786.     JMP    RUNTSL    ;THEN RUN THAT LINE
  787. RETURN:
  788.     CALL    ENDCHK    ;THERE MUST BE A 0DH
  789.     MOV    BX,[STKGOS]    ;OLD STACK POINTER
  790.     OR    BX,BX
  791.     JNZ    RET1    ;SO, WE SAY: "WHAT?"
  792.         JMP     QWHAT
  793. RET1:    XCHG    BX,SP        ;ELSE RESTORE IT
  794.     POP    BX    ;ELSE RESTORE IT
  795.     MOV    [STKGOS],BX    ;AND THE OLD 'STKGOS'
  796.     POP    BX
  797.     MOV    [CURRNT],BX    ;AND THE OLD 'CURRNT'
  798.     POP    DX    ;OLD TEXT POINTER
  799.     CALL    POPA    ;OLD "FOR" PARAMETERS
  800.     CALL    FINISH    ;AND WE ARE BACK HOME
  801. ;
  802. ;
  803. ; ****FOR**** AND ****NEXT****
  804. ;
  805. ;
  806. ; 'FOR' HAS TWO FORMS:
  807. ;    'FOR VAR=EXP1 TO EXP2 STEP EXP3'
  808. ;    'FOR VAR=EXP1 TO EXP2'
  809. ; THE SECOND FORM MEANS THE SAME AS THE FIRST FORM WITH EXP3=1.
  810. ;
  811. ; TBI WILL FIND THE VARIABLE VAR AND SET ITS VALUE TO THE CUR-
  812. ; RENT VALUE OF EXP1. IT ALSO  EVALUATES  EXP2  AND  EXP3  AND
  813. ; SAVES ALL OF THESE TOGETHER  WITH  THE  TEXT  POINTER ETC IN
  814. ; THE 'FOR' SAVE AREA, WHICH CONSISTS OF 'LOPVAR',   'LOPINC',
  815. ; 'LOPLMT', 'LOPLN', AND 'LOPPT'. IFF THERE IS ALREADY   SOME-
  816. ; THING IN THE SAVE AREA (THIS IS  INDICATED  BY  A   NON-ZERO
  817. ; 'LOPVAR'), THEN THE OLD SAVE AREA IS SAVED IN THE STACK  BE-
  818. ; FORE THE NEW ONE OVERWRITES IT.
  819. ;
  820. ; TBI WILL THEN DIG IN THE  STACK  AND  FIND  OUT IFF     THIS
  821. ; SAME VARIABLE WAS USED IN  ANOTHER  CURRENTLY  ACTIVE    FOR
  822. ; LOOP. IT THAT IS THE CASE THEN THE OLD 'FOR'   LOOP IS   DE-
  823. ; IVATED (PURGED FROM THE STACK).
  824. ;
  825. ; 'NEXT VAR' SERVES AS THE LOGICAL (NOT NECESSARILLY PHYSICAL)
  826. ; END OF THE 'FOR' LOOP. THE CONTROL VARIABLE VAR. IS  CHECKED
  827. ; WITH THE 'LOPVAR'. IFF THEY ARE NOT THE SAME, TBI DIGGS   IN
  828. ; THE STACK TO FIND THE RIGHT ONE  AND  PURGES  ALL THOSE THAT
  829. ; DID NOT MATCH. EITHER WAY, TBI THEN ADDS THE 'STEP' TO  THAT
  830. ; VARIABLE AND CHECKS THE RESULT WITH THE LIMIT.  IFF  IT   IS
  831. ; WITHIN THE LIMIT, CONTROL LOOPS BACK TO THE COMMAND  FOLLOW-
  832. ; ING THE 'FOR'. IFF OUTSIDE THE LIMIT, THE SAVE AREA IS PURG-
  833. ; ED AND EXECUTION CONTINUES.
  834. ;
  835. ;
  836. FOR:
  837.     CALL    PUSHA    ;SAVE THE OLD SAVE AREA
  838.     CALL    SETVAL    ;SET THE CONTROL VAR.
  839.     DEC    BX
  840.     MOV    [LOPVAR],BX    ;SAVE TGAT
  841.     MOV    BX,TAB5-1    ;USE 'EXEC' TO LOOK
  842.     JMP    EXEC    ;FOR THE WORD 'TO'
  843. FR1:
  844.     CALL    EXP    ;EVALUATE THE LIMIT
  845.     MOV    [LOPLMT],BX    ;SAVE THAT
  846.     MOV    BX,TAB6-1    ;USED 'EXEC' TO LOOK
  847.     JMP    EXEC    ;FOR THE WORD 'STEP'
  848. FR2:
  849.     CALL    EXP    ;FOUND IT, GET STEP
  850.     JP    FR4    ;FOUND IT, GET STEP
  851. FR3:
  852.     MOV    BX,1    ;NOT FOUND, SET TO ONE
  853. FR4:
  854.     MOV    [LOPINC],BX    ;SAVE THAT TOO
  855. FR5:
  856.     MOV    BX,[CURRNT]    ;SAVE CURRENT LINE #
  857.     MOV    [LOPLN],BX
  858.     XCHG    DX,BX    ;AND TEXT POINTER
  859.     MOV    [LOPPT],BX
  860.     MOV    CX,10    ;DIG INTO STACK TO
  861.     MOV    BX,[LOPVAR]    ;FIND 'LOPVAR'
  862.     XCHG    DX,BX
  863.     MOV    BX,CX    ;BX:=10 NOW
  864.     ADD    BX,SP
  865.     JP    FR7A
  866. FR7:
  867.     ADD    BX,CX
  868. FR7A:    MOV    AX,[BX]    ;GET THAT OLD 'LOPVAR'
  869.     OR    AX,AX
  870.     JZ    FR8    ;0 SAYS NO MORE IN IT
  871.     CMP    AX,DX    ;SAME AS THIS ONE?
  872.     JNZ    FR7
  873.     XCHG    DX,BX
  874.     MOV    BX,0    ;THE OTHER HALF?
  875.     ADD    BX,SP
  876.     MOV    CX,BX
  877.     MOV    BX,10
  878.     ADD    BX,DX
  879.     CALL    MVDOWN    ;AND PURGE 10 WORDS
  880.     XCHG    BX,SP        ;IN THE STACK
  881. FR8:
  882.     MOV    BX,[LOPPT]    ;JOB DONE, RESTORE DE
  883.     XCHG    DX,BX
  884.     CALL    FINISH    ;AND CONTINUE
  885.     ;
  886. NEXT:
  887.     CALL    TSTV    ;GET ADDR OF VAR
  888.     JNC    NX4    ;NO VARIABLE, "WHAT?"
  889.         JMP     QWHAT
  890. NX4:    MOV    [VARNXT],BX    ;YES, SAVE IT
  891. NX0:
  892.     PUSH    DX    ;SAVE TEXT POINTER
  893.     XCHG    DX,BX
  894.     MOV    BX,[LOPVAR]    ;GET VAR IN 'FOR'
  895.     MOV    AL,BH
  896.     OR    AL,BL    ;0 SAY NEVER HAD ONE
  897.     JNZ    NX5    ;SO WE ASK: "WHAT?"
  898.         JMP     AWHAT
  899. NX5:    CMP    DX,BX    ;ELSE WE CHECK THEM
  900.     JZ    NX3    ;OK, THEY AGREE
  901.     POP    DX    ;NO, LET'S SEE
  902.     CALL    POPA    ;PURGE CURRENT LOOP
  903.     MOV    BX,[VARNXT]    ;AND POP ONE LEVEL
  904.     JMP    NX0    ;GO CHECK AGAIN
  905. NX3:
  906.     MOV    DL,[BX]    ;COME HERE WHEN AGREED
  907.     INC    BX
  908.     MOV    DH,[BX]    ;DE = VAL OF VAR
  909.     MOV    BX,[LOPINC]
  910.     PUSH    BX
  911.     ADD    BX,DX
  912.     XCHG    DX,BX    ;ADD ONE STEP
  913.     MOV    BX,[LOPVAR]    ;PUT IT BACK
  914.     MOV    [BX],DL
  915.     INC    BX
  916.     MOV    [BX],DH
  917.     MOV    BX,[LOPLMT]    ;HL-> LIMIT
  918.     POP    AX
  919.     XCHG    AH,AL
  920.     OR    AX,AX
  921.     JNS    NX1    ;STEP > 0
  922.     XCHG    DX,BX
  923. NX1:
  924.     CALL    CKHLDE    ;COMPARE WITH LIMIT
  925.     POP    DX    ;RESTORE TEXT POINTER
  926.     JC    NX2    ;OUTSIDE LIMIT
  927.     MOV    BX,[LOPLN]    ;WITHIN LIMIT, GO
  928.     MOV    [CURRNT],BX    ;BACK TO THE SAVED
  929.     MOV    BX,[LOPPT]    ;'CURRNT' AND TEXT
  930.     XCHG    DX,BX    ;POINTER
  931.     CALL    FINISH    ;POINTER
  932. NX2:
  933.     CALL    POPA    ;PURGE THIS LOOP
  934.     CALL    FINISH
  935. ;
  936. ;
  937. ; ****REM**** AND ****IF**** AND ****LET*****
  938. ;
  939. ;
  940. ; 'REM' CAN BE FOLLOWED BY ANYTHING AND IS IGNORED BY TBI. TBI
  941. ; TREATS IT LIKE AN 'IF' WITH A FALSE CONDITION.
  942. ;
  943. ; 'IF' IS FOLLOWED BY AN EXPR. AS A CONDITION AND ONE OR  MORE
  944. ; COMMANDS (INCLUDING OTHER 'IF'S) SEPERATED  BY  SEMI-COLONS.
  945. ; NOTE THAT THE WORD 'THEN' IS NOT USED.  TBI  EVALUATES   THE
  946. ; EXPR. IFF IT IS NON-ZERO, EXECUTION CONTINUES. IFF THE EXPR.
  947. ; IS ZERO, THE COMMANDS THAT FOLLOW ARE IGNORED AND  EXECUTION
  948. ; CONTINUES AT THE NEXT LINE.
  949. ;
  950. ; 'IPUT' COMMANS IS LIKE THE 'PRINT' COMMAND, AND IS  FOLLOWED
  951. ; BY A LIST OF ITEMS. IFF THE ITEM IS A  STRING  IN  SINGLE OR
  952. ; DOUBLE QUOTES, OR IS A BACK-ARROW, IT HAS THE SAME EFFEDT AS
  953. ; PRINTED OUT FOLLOWED BY A COLON. THEN TBI WAITS FOR AN EXPR.
  954. ; TO BE TYPEN IN. THE VARIABLE IS THEN  SET  TO  THE  VALUE OF
  955. ; THIS EXPR. IFF THE VARIABLE IS PROCEDED BY A STRING  PRINTED
  956. ; FOLLOWED BY A COLON. TBI THEN WAITS FOR INPUT EXPR. AND SETS
  957. ; THE VARIABLE TO THE VALUE OF THE EXPR.
  958. ;
  959. ; IFF THE INPUT EXPR. IS INVALID,  TBI  WILL  PRINT  "WHAT?" ,
  960. ; "HOW?",OR "SORRY" AND REPRINT THE PROMPT AND REDO THE INPUT.
  961. ; THE EXECUTION WILL NOT TERMINATE UNLESS YOU TYPE CONTROL-C .
  962. ; THIS IS HANDLED IN 'INPERR'.
  963. ;
  964. ; 'LET' IS FOLLOWED BY A LIST OF ITEMS SEPERATED  BY  COMMAS .
  965. ; EACH ITEM CONSISTS OF A VARIABLE,  AN  EQUAL  SIGN,  AND  AN
  966. ; EXPR. TBI EVALUATES THE EXPR. AND SETS THE VARIABLE TO  THAT
  967. ; VALUE. TBI WILL ALSO HANDLE 'LET' COMMAND WITHOUT THE   WORD
  968. ; 'LET'. THIS IS DONE BY 'DEFLT'.
  969. ;
  970. ;
  971. ;
  972. REM:
  973.     MOV    BX,0    ;****REM****
  974.     JP    IFF1A    ;JUMP AROUND EXPR
  975.     ;
  976. IFF:
  977.     CALL    EXP    ;****IF****
  978. IFF1A:    CMP    BX,0    ;IS THE EXPR = 0?
  979.     JZ    IFF1    ;NO, CONTINUE
  980.         JMP     RUNSML
  981. IFF1:    CALL    FNDSKP    ;YES, SIKP REST OF LINE
  982.     JC    IFF2    ;YES, SIKP REST OF LINE
  983.         JMP     RUNTSL
  984. IFF2:    JMP    RSTART    ;YES, SIKP REST OF LINE
  985.     ;
  986. INPERR:
  987.     MOV    BX,[STKINP]    ;****INPERR****
  988.     XCHG    BX,SP        ;RESTORE OLD STACK POINTER
  989.     POP    BX    ;AND OLD 'CURRNT'
  990.     MOV    [CURRNT],BX
  991.     POP    DX
  992.     POP    DX    ;REDO INPUT
  993.     ;
  994. INPUT:    EQU    $    ;****INPUT****
  995. IP1:
  996.     PUSH    DX    ;SAVE IN CASE OF ERROR
  997.     CALL    QTSTG    ;IS NEXT ITEM A STRING?
  998.     JP    IP2    ;NO
  999.     CALL    TSTV    ;YES, BUT FOLLOWED BY A
  1000.     JC    IP4    ;VARIABLE? NO.
  1001.     JP    IP3    ;YES. INPUT VAR.
  1002. IP2:
  1003.     PUSH    DX    ;SAVE FOR 'PRTSTG'
  1004.     CALL    TSTV    ;MUST BE A VAR NOW
  1005.     JNC    IP2A    ;"WHAT" IT IS NOT!
  1006.         JMP     QWHAT
  1007. IP2A:    MOV    SI,DX
  1008.     LODB        ;GET READY FOR 'RTSTG'
  1009.     MOV    CL,AL
  1010.     SUB    AL,AL
  1011.     MOV    DI,DX
  1012.     STOB
  1013.     POP    DX
  1014.     CALL    PRTSTG    ;PRINT STRING AS PROMPT
  1015.     MOV    AL,CL
  1016.     DEC    DX
  1017.     MOV    DI,DX
  1018.     STOB
  1019. IP3:
  1020.     PUSH    DX
  1021.     XCHG    DX,BX
  1022.     MOV    BX,[CURRNT]    ;ALSO SAVE 'CURRNT'
  1023.     PUSH    BX
  1024.     MOV    BX,IP1
  1025.     MOV    [CURRNT],BX    ;NEG NUMBER AS FLAG
  1026.     MOV    [STKINP],SP
  1027.     PUSH    DX    ;OLD HL
  1028.     MOV    AL,':'    ;PRINT THIS TOO
  1029.     CALL    GETLN    ;AND GET A LINE
  1030. IP3A:
  1031.     MOV    DX,BUFFER    ; POINTS TO BUFFER
  1032.     CALL    EXP    ;EVALUATE INPUT
  1033.     NOP            ;CAN BE 'CALL ENDCHK'
  1034.     NOP         ;CAN BE 'CALL ENDCHK'
  1035.     NOP         ;CAN BE 'CALL ENDCHK'
  1036.     POP    DX    ;OK,GET OLD HL
  1037.     XCHG    DX,BX    ;OK,GET OLD HL
  1038.     MOV    [BX],DX
  1039.     POP    BX    ;GET OLD 'CURRNT'
  1040.     MOV    [CURRNT],BX
  1041.     POP    DX    ;AND GET OLD TEXT POINTER
  1042. IP4:
  1043.     POP    AX
  1044.     MOV    AH,','
  1045.     CALL    IGNBLNK
  1046.     JNZ    IP5
  1047.     JP    IP1    ;YES, MORE ITEMS
  1048. IP5:
  1049.     CALL    FINISH
  1050.     ;
  1051. DEFLT:
  1052.     MOV    SI,DX
  1053.     LODB    ;****DEFLT****
  1054.     CMP    AL,0DH    ;EMPTY LINE IS OK
  1055.     JZ    LT1    ;ELSE IT IS 'LET'
  1056.     ;
  1057. LET:
  1058.     CALL    SETVAL    ;****LET****
  1059.     MOV    AH,','
  1060.     CALL    IGNBLNK
  1061.     JNZ    LT1
  1062.     JP    LET    ;ITEM BY ITEM
  1063. LT1:
  1064.     CALL    FINISH    ;UNTIL FINISH
  1065. ;
  1066. ;
  1067. ; ****EXPR****
  1068. ;
  1069. ; 'EXPR' EVALUATES ARITHMETICAL OR LOGICAL EXPRESSIONS.
  1070. ;    <EXPR>::=<EXPR2>
  1071. ;                <EXPR2><REL.OP><EXPR2>
  1072. ;
  1073. ; WHERE <REL.OP> IS ONE OF THE OPERATORS IN TAB8 AND THE RE-
  1074. ; SULT OF THESE OPERATIONS IS 1 IFF TRUE AND  0  IFF  FALSE.
  1075. ;
  1076. ;    <EXPR2>::=(+ OR -)<EXPR3>(+ OR -<EXPR3>(....)
  1077. ;
  1078. ; WHERE () ARE OPTIONAL AND (....) ARE OPTIONAL REPEATS.
  1079. ;
  1080. ;    <EXPR3>::=<EXPR4>(<* OR /><EXPR4>)(....)
  1081. ;    <EXPR4>::=<VARIABLE>
  1082. ;            <FUNCTION>
  1083. ;            (<EXPR>)
  1084. ;
  1085. ; <EXPR> IS RECURSIVE SO THAT VARIABLE '@' CAN HAVE AN EXPR
  1086. ; AS INDEX, FUCTIONS CAN HAVE AN <EXPR> AS ARGUMENTS,   AND
  1087. ; <EXPR4> CAN BE AN <EXPR> IN PARANTHESES.
  1088. ;
  1089. ;
  1090. EXP:    CALL    EXPR2
  1091.     PUSH    BX
  1092. EXPR1:
  1093.     MOV    BX,TAB8-1    ;LOOKUP REL.OP
  1094.     JMP    EXEC    ;GO DO IT
  1095. XP11:
  1096.     CALL    XP18
  1097.     JC    RET    ;NO RETURN HL=0
  1098.     MOV    BL,AL    ;YES, RETURN HL=1
  1099.     RET
  1100. XP12:
  1101.     CALL    XP18
  1102.     JZ    RET    ;FALSE, RETURN HL=0
  1103.     MOV    BL,AL    ;TRUE, RETURN HL=1
  1104.     RET
  1105. XP13:
  1106.     CALL    XP18    ;REL.OP '>'
  1107.     JZ    RET    ;FALSE
  1108.     JC    RET    ;ALSO FALSE, HL=0
  1109.     MOV    BL,AL    ;TRUE, HL=1
  1110.     RET
  1111. XP14:
  1112.     CALL    XP18    ;REL OP '<='
  1113.     MOV    BL,AL    ;SET HL=1
  1114.     JZ    RET    ;REL. TRUE, RETURN
  1115.     JC    RET    ;REL. TRUE, RETURN
  1116.     MOV    BL,BH    ;ELSE SET HL=0
  1117.     RET
  1118. XP15:
  1119.     CALL    XP18    ;REL OP '='
  1120.     JNZ    RET    ;FALSE, RETURN HL=0
  1121.     MOV    BL,AL    ;ELSE SET HL=1
  1122.     RET
  1123. XP16:
  1124.     CALL    XP18    ;REL.OP '<'
  1125.     JNC    RET    ;FALSE, RETURN HL=0
  1126.     MOV    BL,AL    ;ELSE SET HL=1
  1127.     RET
  1128. XP17:
  1129.     POP    BX    ;NOT REL OP
  1130.     RET    ;RETURN HL=<EPTR2>
  1131. XP18:
  1132.     MOV    AL,CL    ;SUBROUTINE FOR ALL
  1133.     POP    BX    ;REL.OP'S
  1134.     POP    CX    ;REL.OP'S
  1135.     PUSH    BX    ;REVERSE TOP OF STACK
  1136.     PUSH    CX    ;REVERSE TOP OF STACK
  1137.     MOV    CL,AL
  1138.     CALL    EXPR2    ;GET 2ND EXPRESSION
  1139.     XCHG    DX,BX    ;VALUE IN DE NOW
  1140.     POP    AX
  1141.     PUSH    BX
  1142.     MOV    BX,AX    ;LAST 3 INSTR FOR XTHL INST!
  1143.     CALL    CKHLDE    ;COMPARE 1ST WITH SECOND
  1144.     POP    DX
  1145.     MOV    BX,0    ;SET HL=0, A=1
  1146.     MOV    AL,1    ;SET HL=0, A=1
  1147.     RET
  1148.     ;
  1149. EXPR2:
  1150.     MOV    AH,'-'
  1151.     CALL    IGNBLNK    ;NEGATIVE SIGN?
  1152.     JNZ    XP21
  1153.     MOV    BX,0    ;YES, FAKE '0-'
  1154.     JP    XP26    ;TREAT LIKE SUBTRACT
  1155. XP21:
  1156.     MOV    AH,'+'    ;POSITIVE SIGN?
  1157.     CALL    IGNBLNK
  1158. XP22:
  1159.     CALL    EXPR3    ;1ST <EXPR3>
  1160. XP23:
  1161.     MOV    AH,'+'
  1162.     CALL    IGNBLNK    ;ADD?
  1163.     JNZ    XP25    ;NOTE OFFSET WHAS 21 BYTES IN 8080 VERSION
  1164.     PUSH    BX    ;YES, SAVE VALUE
  1165.     CALL    EXPR3    ;GET 2ND <EXPR3>
  1166. XP24:
  1167.     XCHG    DX,BX    ;2ND IN DE
  1168.     POP    AX    ;THIS + NEXT 2 LINES FOR 8080 XTHL INST!!
  1169.     PUSH    BX
  1170.     MOV    BX,AX    ;BX <-> [SP] NOW, [SP]->BUFFER,BX=OLD EXPR3
  1171.     ADD    BX,DX
  1172.     POP    DX
  1173.     JNO    XP23    ;CHECK FOR OVERFLOW
  1174. XP24A:    JMP    QHOW    ;ELSE WE HAVE OVERFLOW
  1175. XP25:
  1176.     MOV    AH,'-'
  1177.     CALL    IGNBLNK    ;SUBTRACT?
  1178.     JNZ    RET
  1179. XP26:    PUSH    BX    ;YES, SAVE 1ST <EXPR3>
  1180.     CALL    EXPR3    ;GET 2ND <EXPR3>
  1181.     CALL    CHGSGN
  1182.     JP    XP24
  1183.     ;
  1184. EXPR3:
  1185.     CALL    EXPR4    ;GET 1ST <EXPR4>
  1186. XP31:
  1187.     MOV    AH,'*'
  1188.     CALL    IGNBLNK    ;MULTIPLY?
  1189.     JNZ    XP34
  1190.     PUSH    BX    ;YES, SAVE 1ST
  1191.     CALL    EXPR4    ;AND GET 2ND <EXPR4>
  1192.     XCHG    DX,BX    ;2ND IN DE NOW
  1193.     POP    AX    ;SUBSITUTE FOR 8080 XTHL
  1194.     PUSH    BX
  1195.     IMUL    AX,DX    ;AX:=AX*DX
  1196.     JO    XP32    ;SEE INTEL BOOK ON OVERFLOW FLAG
  1197.     MOV    BX,AX    ;RESULT NOW IN BX
  1198.     JP    XP35    ;LOOK FOR MORE
  1199. XP34:
  1200.     MOV    AH,'/'
  1201.     CALL    IGNBLNK    ;DIVIDE?
  1202.     JNZ    RET
  1203.     PUSH    BX    ;YES, SAVE 1ST <EXPR4>
  1204.     CALL    EXPR4    ;AND GET SECOND ONE
  1205.     XCHG    DX,BX    ;PUT 2ND IN DE
  1206.     POP    AX    ;REPLACEMENT FOR XTHL
  1207.     PUSH    BX
  1208.     MOV    BX,AX
  1209.     OR    DX,DX
  1210.     JNZ    XP34A    ;SAY "HOW?"
  1211. XP32:    JMP    AHOW
  1212. XP34A:    CALL    DIVIDE    ;USE SUBROUTINE
  1213.     MOV    BX,CX    ;GET RESULT
  1214.     MOV    CX,6    ;SIX SPACES
  1215. XP35:
  1216.     POP    DX    ;AND TEXT POINTER
  1217.     JP    XP31    ;LOOK FOR MORE TERMS
  1218.     ;
  1219. EXPR4:
  1220.     MOV    BX,TAB4-1    ;FIND FUCNTION IN TAB4
  1221.     JMP    EXEC    ;AND GOT DO IT
  1222. XP40:
  1223.     CALL    TSTV    ;NO, NOT A FUNCTION
  1224.     JC    XP41    ;NOR A VARIABLE
  1225.     MOV    AL,[BX]    ;VARIABLE
  1226.     LAHF
  1227.     INC    BX
  1228.     SAHF
  1229.     MOV    BH,[BX]    ;VALUE IN HL
  1230.     MOV    BL,AL    ;VALUE IN HL
  1231.     RET
  1232. XP41:
  1233.     CALL    TSTNUM    ;OR IS IT A NUMBER?
  1234.     MOV    AL,CH    ;# OF DIGITS
  1235.     OR    AL,AL
  1236.     JNZ    RET    ;OK
  1237. PARN:
  1238.     MOV    AH,'('
  1239.     CALL    IGNBLNK    ;NO DIGIT, MUST BE
  1240.     JNZ    PARN1
  1241.     CALL    EXP    ;"(EXPR)"
  1242. PARN1:    MOV    AH,')'
  1243.     CALL    IGNBLNK    ;"(EXPR)"
  1244.     JNZ    XP43    ;******WHY CHECK THIS?******
  1245. XP42:
  1246.     RET
  1247. XP43:
  1248.     JMP    QWHAT    ;ELSE SAY: "WHAT?"
  1249.     ;
  1250. RND:
  1251.     CALL    PARN    ;****RND(EXPR)****
  1252.     OR    BX,BX
  1253.     JNS    RND1    ;MUST BE POSITIVE
  1254.     JNZ    RND1    ;AND NON-ZERO
  1255.         JMP     QHOW
  1256. RND1:
  1257.     PUSH    CX
  1258.     PUSH    DX
  1259.     MOV    AH,2CH    ;GET TIME
  1260.     INT    33    ;ASK MS-DOS
  1261.     MOV    AX,327
  1262.     MOV    DH,0
  1263.     MUL    AX,DX    ; 0<=AX<=32700
  1264.     XCHG    DX,BX
  1265.     MOV    BX,AX
  1266.     CALL    DIVIDE    ;RND(N)=MOD(M,N)+1
  1267.     POP    DX
  1268.     POP    CX
  1269.     INC    BX
  1270.     RET
  1271.     ;
  1272. ABS:
  1273.     CALL    PARN    ;****ABS(EXPR)****
  1274.     CALL    CHKSGN    ;CHECK SIGN
  1275.     OR    AX,BX
  1276.     JNS    RET    ;OK
  1277.     JMP    QHOW    ;SO SAY: "HOW?"
  1278. SIZE:
  1279.     MOV    BX,[TXTUNF]    ;****SIZE****
  1280.     PUSH    DX    ;GET THE NUMBER OF FREE
  1281.     XCHG    DX,BX    ;BYTES BETWEEN 'TXTUNF'
  1282. SIZEA:
  1283.     MOV    BX,VARBGN    ;AND 'VARBGN'
  1284.     SUB    BX,DX
  1285.     POP    DX
  1286.     RET
  1287. ;
  1288. ;
  1289. ; ****OUT**** AND ****INP**** AND ****WAIT**** AND
  1290. ; ****POKE**** AND ****PEEK**** AND ****USR****
  1291. ;
  1292. ;
  1293. ; 'OUT I,J(,K,L)'
  1294. ;
  1295. ; OUTPUTS EXPRESSION 'J' TO PORT 'I', AND MAY BE REPEATED AS
  1296. ; IN DATA 'L' TO PORT 'K' AS MANY TIMES AS NEEDED. THIS COM-
  1297. ; MAND MODIFIES *, A SMALL SECTION OF CODE ABOVE ADDRESS 2K.
  1298. ;
  1299. ; 'INP (I)'
  1300. ;
  1301. ; THIS FUNCTION RETURNDS DATA READ FROM  INPUT  PORT 'I'  AS
  1302. ; ITS VALUE. IT ALSO MODIFIES CODE JUST ABOVE 2K.
  1303. ;
  1304. ; 'WAIT I,J,K'
  1305. ;
  1306. ; THIS COMMAND READS THE STATUS OF PORT 'I', EXCLUSIVE  OR'S
  1307. ; THE RESULT WITH 'K', IF THE RESULT IS ONE, OR IF NOT  WITH
  1308. ; ZERO, AND'S WITH 'J' AND RETURNS WHEN THE RESULT IS   NON-
  1309. ; ZERO. ITS MODIFIED CODE IS ALSO ABOVE 2K.
  1310. ;
  1311. ; 'POKE I,J(,K,L)
  1312. ;
  1313. ; THIS COMMAND WORKS LIKE OUT EXCEPT THAT IT PUTS  DATA  'J'
  1314. ; INTO MEMORY LOCATION 'I'.
  1315. ;
  1316. ; 'PEEK (I)'
  1317. ;
  1318. ; THIS FUNCTION WORKS LIKE INP EXCEPT THAT IT PUTS DATA  'J'
  1319. ; FROM MEMORY LOCATION 'I'.
  1320. ;
  1321. ; 'USR(I(,J))'
  1322. ;
  1323. ; USR CALL A MACHINE LANGUAGE SUBROUTINE AT LOCATION 'I'  IF
  1324. ; THE OPTIONAL PARAMETER 'J' IS USED ITS VALUE IS PASSED  IN
  1325. ; HL. THE VALUE OF THE FUNCTION SHOULD BE RETURNED IN HL.
  1326. ;
  1327. ;
  1328. OUTCMD:
  1329.     CALL    EXP
  1330.     MOV    AL,BL
  1331.     MOV    [OUTIO+1],AL
  1332.     MOV    AH,','
  1333.     CALL    IGNBLNK
  1334.     JZ    OUT1    ;FOUND MORE TO WORK ON
  1335.     JMP    QWHAT
  1336. OUT1:    CALL    EXP
  1337.     MOV    AL,BL
  1338.     CALL    OUTIO
  1339.     MOV    AH,','
  1340.     CALL    IGNBLNK
  1341.     JNZ    OUTCMD1
  1342.     JP    OUTCMD
  1343. OUTCMD1:CALL    FINISH
  1344. WAITCM:
  1345.     CALL    EXP
  1346.     MOV    AL,BL
  1347.     MOV    [WAITIO+1],AL
  1348.     MOV    AH,','
  1349.     CALL    IGNBLNK
  1350.     JZ    WT1
  1351.     JMP    QWHAT
  1352. WT1:    CALL    EXP
  1353.     PUSH    BX
  1354.     MOV    AH,','
  1355.     CALL    IGNBLNK
  1356.     JNZ    WAIT1
  1357.     CALL    EXP
  1358.     MOV    AL,BL
  1359.     POP    BX
  1360.     MOV    BL,AL
  1361.     JP    WAIT2
  1362. WAIT1:    MOV    BH,0
  1363. WAIT2:    JMP    WAITIO
  1364. INP:
  1365.     CALL    PARN
  1366.     MOV    AL,BL
  1367.     MOV    [INPIO+1],AL
  1368.     MOV    BX,0
  1369.     JMP    INPIO
  1370.     JP    QWT
  1371. POKE:
  1372.     CALL    EXP
  1373.     PUSH    BX
  1374.     MOV    AH,','
  1375.     CALL    IGNBLNK
  1376.     JZ    POK1
  1377.     JMP    QWHAT
  1378. POK1:    CALL    EXP
  1379.     MOV    AL,BL
  1380.     POP    BX
  1381.     MOV    [BX],AL
  1382.     MOV    AH,','
  1383.     CALL    IGNBLNK
  1384.     JNZ    POK2
  1385.     JP    POKE
  1386. POK2:    CALL    FINISH
  1387. PEEK:
  1388.     CALL    PARN
  1389.     MOV    BL,[BX]
  1390.     MOV    BH,0
  1391.     RET
  1392.     JMP    QWHAT
  1393. USR:
  1394.     PUSH    CX
  1395.     MOV    AH,'('
  1396.     CALL    IGNBLNK
  1397.     JNZ    QWT
  1398.     CALL    EXP    ;EXPR
  1399.     MOV    AH,')'
  1400.     CALL    IGNBLNK    ;EXPR
  1401.     JNZ    PASPRM
  1402.     PUSH    DX
  1403.     MOV    DX,USRET
  1404.     PUSH    DX
  1405.     PUSH    BX
  1406.     RET    ;CALL USR ROUTINE
  1407. PASPRM:
  1408.     MOV    AH,','
  1409.     CALL    IGNBLNK
  1410.     JNZ    USRET1
  1411.     PUSH    BX
  1412.     CALL    EXP
  1413.     MOV    AH,')'
  1414.     CALL    IGNBLNK
  1415.     JNZ    USRET1
  1416.     POP    CX
  1417.     PUSH    DX
  1418.     MOV    DX,USRET
  1419.     PUSH    DX
  1420.     PUSH    CX
  1421.     RET    ;CALL USR ROUTINE
  1422. USRET:
  1423.     POP    DX
  1424. USRET1:    POP    CX
  1425.     RET
  1426. QWT:    JMP    QWHAT
  1427. ;
  1428. ;
  1429. ; ****DIVIDE**** AND ****CHKSGN****
  1430. ; ****CHKSGN**** AND ****CKHLDE****
  1431. ;
  1432. ;
  1433. ; 'DIVIDE DIVIDES BX BY DX, RESULT IN CX, REMAINDER IN BX
  1434. ;
  1435. ; 'CHKSGN' CHECKS SIGN OF BX. IFF +, NO CHANGE. IFF -, CHANGE
  1436. ;    SIGN AND FLIP SIGN OF C
  1437. ;
  1438. ; 'CHGSGN' CHANGES SIGN OF BX AND CL UNCONDITIONALLY.
  1439. ;
  1440. ; 'CKHLDE' CHECK SIGN OF BX AND DX. IFF DIFFERENT, BX AND DX
  1441. ; ARE INTERCHANGED. IFF SAME SIGN, NOT INTERCHANGED.   EITHER
  1442. ; CASE, BX AND DX ARE THEN COMPARED TO SET THE FLAGS.
  1443. ;
  1444. ;
  1445. DIVIDE:
  1446.     PUSH    DX    ;PRESERVE DX ACCROSS CALL
  1447.     PUSH    DX
  1448.     XOR    DX,DX
  1449.     POP    CX
  1450.     MOV    AX,BX
  1451.     IDIV    AX,CX
  1452.     MOV    CX,AX    ;QUOTIENT
  1453.     MOV    BX,DX    ;REMAINDER
  1454.     POP    DX    ;DX RESTORED
  1455.     RET
  1456.     ;
  1457. CHKSGN:
  1458.     OR    BX,BX    ;SET FLAGS TO CHECK SIGN
  1459.     JNS    RET    ;IFF -, CHANGE SIGN
  1460.     ;
  1461. CHGSGN:
  1462.     NOT    BX    ;****CHGSGN****
  1463.     INC    BX
  1464.     XOR    CH,128
  1465.     RET
  1466.     ;
  1467. CKHLDE:
  1468.     MOV    AL,BH
  1469.     XOR    AL,DH    ;SAME SIGN?
  1470.     JNS    CK1    ;YES, COMPARE
  1471.     XCHG    DX,BX
  1472. CK1:
  1473.     CMP    BX,DX
  1474.     RET
  1475. ;
  1476. ;
  1477. ; ****SETVAL**** AND ****FIN**** AND ****ENDCHK****
  1478. ; ****ERROR**** AND FRIENDS
  1479. ;
  1480. ;
  1481. ; 'SETVAL' EXPECTS A VARIABLE, FOLLOWED BY AN EQUAL SIGN AND
  1482. ; THEN AN EXPR. IT EVALUATES THE EXPR AND SETS THE  VARIABLE
  1483. ; TO THAT VALUE.
  1484. ;
  1485. ; 'FIN' CHECKS THE END OF A COMMAND. IFF IT ENDED WITH ";" ,
  1486. ; EXECUTION CONTINUES. IFF IT ENDED WITH A CR, IT FINDS  THE
  1487. ; NEXT LINE AND CONTINUES FROM THERE.
  1488. ;
  1489. ; 'ENDCHK' CHECKS IFF A COMMAND IS ENDED WITH A CR, THIS  IS
  1490. ; REQUIRED IN CERTAIN COMMANDS. (GOTO, RETURN, AND STOP,ETC)
  1491. ;
  1492. ; 'ERROR' PRINTS THE STRING POINTED BY DX (AND ENDS  WITH  A
  1493. ; CR). IT THEN PRINTS THE LINE POINTED BY 'CURRNT' WITH A ?.
  1494. ; INSERTED AT WHERE THE OLD TEXT POINTER (SHOULD  BE  ON TOP
  1495. ; OF THE STACK) POINTS TO. EXECUTION OF TB IS  STOPPED   AND
  1496. ; TBI IS RESTARTED. HOWEVER, IFF 'CURRNT' -> ZERO (INDICAT -
  1497. ; ING A DIRECT COMMAND), THE DIRECT COMMAND IS NOT PRINTED ,
  1498. ; AND IFF 'CURRNT' -> NEGATIVE # (INDICATING 'INPUT' COMMAND
  1499. ; THE INPUT LINE IS NOT PRINTED AND EXECUTION IS NOT TERMIN-
  1500. ; ATED BUR CONTINUED AT 'INPERR').
  1501. ;
  1502. ; RELATED TO 'ERROR' ARE THE FOLLOWING:
  1503. ;
  1504. ;    'QWHAT' SAVES TEXT POINTER IN STACK AND GETS MESSAGE
  1505. ;        "WHAT?"
  1506. ;    'AWHAT'    JUST GETS MESSAGE "WHAT?" AND JUMPS TO ERROR
  1507. ;
  1508. ;    'QSORRY' AND 'ASORRY' DO THE SAME KIND OF THING.
  1509. ;
  1510. ;    'QHOW' AND 'AHOW' IN THE ZERO PAGE SECTION ALSO   DO
  1511. ;        THIS.
  1512. ;
  1513. ;
  1514. SETVAL:
  1515.     CALL    TSTV    ;SEE IT IT'S A VARIABLE
  1516.     JC    QWHAT    ;"WHAT" NO VARIABLE
  1517.     PUSH    BX    ;SAVE ADDR OF VARIABLE
  1518.     MOV    AH,'='
  1519.     CALL    IGNBLNK
  1520.     JNZ    SV1
  1521.     CALL    EXP
  1522.     MOV    CX,BX    ;VALUE IN CX NOW
  1523.     POP    BX    ;GET ADDR
  1524.     MOV    [BX],CL    ;SAVE VALUE
  1525.     INC    BX
  1526.     MOV    [BX],CH    ;SAVE VALUE
  1527.     RET
  1528. SV1:
  1529.     JMP    QWHAT    ;NO '=' SIGN
  1530.     ;
  1531. FIN:
  1532.     MOV    AH,';'
  1533.     CALL    IGNBLNK
  1534.     JNZ    FI1
  1535.     POP    AX
  1536.     JMP    RUNSML
  1537. FI1:
  1538.     MOV    AH,0DH
  1539.     CALL    IGNBLNK
  1540.     JNZ    RET
  1541.     POP    AX
  1542.     JMP    RUNNXL    ;RUN NEXT LINE
  1543. FI2:
  1544.     RET    ;ELSE RETURN TO CALLER
  1545.     ;
  1546. ENDCHK:
  1547.     MOV    AH,0DH    ;END WITH CR?
  1548.     CALL    IGNBLNK
  1549.     JZ    RET    ;OK, ELSE SAY "WHAT?"
  1550.     ;
  1551. QWHAT:
  1552.     PUSH    DX    ;****QWHAT****
  1553. AWHAT:
  1554.     MOV    DX,WHAT    ;****AWHAT****
  1555. ERROR:
  1556.     SUB    AL,AL    ;****ERROR****
  1557.     CALL    PRTSTG    ;PRINT 'WHAT?','HOW?'
  1558.     POP    DX
  1559.     MOV    SI,DX
  1560.     LODB
  1561.     PUSH    AX    ;SAVE THE CHARACTER
  1562.     SUB    AL,AL    ;AND PUT A ZERO THERE
  1563.     MOV    DI,DX
  1564.     STOB
  1565.     MOV    BX,[CURRNT]    ;GET CURRENT LINE #
  1566.     CMP    W,[CURRNT],0    ;DIRECT COMMAND?
  1567.     JNZ    ERR1    ;IFF ZERO, JUST RESTART
  1568.     JP    ERR2    ;SAVE A BYTE
  1569. ERR1:    MOV    AL,[BX]    ;IFF NEGATIVE,
  1570.     OR    AL,AL
  1571.     JNS    ERR1A
  1572.     JMP    INPERR    ;REDO INPUT
  1573. ERR1A:    CALL    PRTLN    ;ELSE PRINT THE LINE
  1574.     DEC    DX
  1575.     POP    AX
  1576.     MOV    DI,DX
  1577.     STOB    ;RESTORE THE CHAR
  1578.     MOV    AL,63    ;PRINT A '?'
  1579.     CALL    CHROUT
  1580.     SUB    AL,AL    ;AND THE REST OF THE
  1581.     CALL    PRTSTG    ;LINE
  1582. ERR2:    JMP    RSTART    
  1583. QSORRY:
  1584.     PUSH    DX    ;****QSORRY****
  1585. ASORRY:
  1586.     MOV    DX,SORRY    ;****ASORRY****
  1587.     JP    ERROR
  1588. ;
  1589. ;
  1590. ; ****GETLN**** AND ****FNDLN****
  1591. ;
  1592. ;
  1593. ; 'GETLN' READS AN INPUT LINE INTO 'BUFFER'. IT FIRST PROMPTS
  1594. ; THE CHARACTER IN A (GIVEN BY THE CALLER), THEN IT FILLS THE
  1595. ; BUFFER AND ECHOS IT. IT USES BDOS PRIMITIVES TO  ACCOMPLISH
  1596. ; THIS. ONCE A FULL LINE IS READ IN, 'GETLN' RETURNS.
  1597. ;
  1598. ; 'FNDLN' FINDS A LINE WITH A GIVEN LINE #(IN BX) IN THE TEXT
  1599. ; SAVE AREA. DX IS USED AS THE TEXT POINTER. IFF THE LINE  IS
  1600. ; FOUND, DX WILL POINT TO THE BEGINNING OF THAT LINE IFF THAT
  1601. ; LINE (I.E. THE LOW BYTE OF THE LINE #), AND FLAGS ARE NC&Z.
  1602. ; IFF THAT LINE IS NOT THERE AND A LINE WITH A HIGHER LINE  #
  1603. ; IS FOUND, DX POINTS TO THERE AND FLAGS ARE NC&NZ.  IFF   WE
  1604. ; REACHED THE END OF TEXT SAVE AREA AND CANNOT FIND THE LINE,
  1605. ; FLAGS ARE C&NZ.
  1606. ; 'FNDLN' WILL INITIALIZE DX TO THE  BEGINNING  OF  THE  TEXT
  1607. ; SAVE AREA TO START THE SEARCH. SOME OTHER ENTRIES  OF  THIS
  1608. ; ROUTINE WILL NOT INITIALIZE DX AND DO THE SEARCH.
  1609. ;
  1610. ; 'FNDLNP' WILL START WITH DX AND SEARCH FOR THE LINE #.
  1611. ;
  1612. ; 'FNDNXT' WILL BUMP DX BY  2, FIND A 0DH AND THEN START  THE
  1613. ;    SEARCH.
  1614. ; 'FNDSKP' USES DX TO FIND A CR, AND THEN STARTS THE SEARCH.
  1615. ;
  1616. ;
  1617. ;
  1618. GETLN:
  1619.     CALL    CHROUT    ;****GETLN****
  1620. GL1:
  1621.     MOV    DX,BUFFER-2
  1622.     PUSH    DX
  1623.     MOV    AH,BCONIN ;BUFFERED CONSOLE INPUT
  1624.     INT    33    ;CALL MS-DOS
  1625.     POP    DX
  1626.     ADD    DL,[BUFFER-1]
  1627.     INC    DX
  1628.     INC    DX
  1629.     INC    DX
  1630.     MOV    DI,DX    ;FOR CONSISTANCY
  1631.     PUSH    DX
  1632.     CALL    CRLF    ;NEED CRLF
  1633.     POP    DX
  1634.     RET    ;WE'VE GOT A LINE
  1635. ;
  1636. ; AT ENTRY BX -> LINE # TO BE FOUND
  1637. ;
  1638. FNDLN:
  1639.     OR    BX,BX    ;CHECK SIGN OF BX
  1640.     JNS    FND1    ;IT CAN'T BE -
  1641.     JMP    QHOW    ;ERROR
  1642. FND1:    MOV    DX,TXTBGN
  1643.     ;
  1644. FNDLNP:
  1645. FL1:
  1646.     PUSH    BX    ;SAVE LINE #
  1647.     MOV    BX,[TXTUNF]    ;CHECK IFF WE PASSED END
  1648.     DEC    BX
  1649.     CMP    BX,DX    ;SUBSTITUTE FOR CALL 4
  1650.     POP    BX    ;GET LINE # BACK
  1651.     JC    RET    ;C, NZ PASSED END
  1652.     MOV    SI,DX
  1653.     LODW
  1654.     CMP    AX,BX
  1655.     JC    FL2
  1656.     RET    ;NC,Z:FOUND;NC,NZ:NOT FOUND
  1657.     ;
  1658. FNDNXT:                 ;****FNDNXT****
  1659.     INC    DX
  1660. FL2:
  1661.     INC    DX
  1662.     ;
  1663. FNDSKP:
  1664.     MOV    SI,DX
  1665.     LODB    ;****FNDSKP****
  1666.     CMP    AL,0DH    ;TRY TO FIND CR
  1667.     JNZ    FL2    ;KEEP LOOKING
  1668.     INC    DX
  1669.     JP    FL1    ;CHECK IFF END OF TEXT
  1670. ;
  1671. ;
  1672. ; **** PRTSTG **** QTSTG **** PRTNUM **** PRTLN ****
  1673. ;
  1674. ;
  1675. ; 'PRTSTG PRINTS A STRING POINTED TO BY DX. IT STOPS PRINTING
  1676. ; AND RETURNS TO CALLER WHEN EITHER A 0DH IS PRINTED OR  WHEN
  1677. ; THE NEXT BYTE IS THE SAMES AS WHAT WAS IN A  ( GIVEN BY THE
  1678. ; CALLER). OLD AL IS STORED IN CH, OLD CH IS LOST.
  1679. ;
  1680. ; 'QTSTG' LOOKS FOR A BACK-SLASH,  SINGLE QUOTE,   OR  DOUBLE
  1681. ; QUOTE. IFF NONE OF THESE, RETURN TO CALLER. IF BACK SLASH \
  1682. ; OUTPUT A ODH WITHOUT A LF. IFF SINGLE OR DOUBLE QUOTE,PRINT
  1683. ; THE STRING IN THE QUOTE AND DEMANDS A MATCHING UNQUOTE. AF-
  1684. ; TER THE PRINTING THE NEXT 3 BYTES OF THE CALLER  IS SKIPPED
  1685. ; OVER (USUALLY A JMP INSTRUCTION).
  1686. ;
  1687. ; 'PRTNUM' PRINTS THE NUMBER IN HL. LEADING BLANKS  ARE ADDED
  1688. ; IFF NEEDED TO PAD THE NUMBER OF SPACES TO THE NUMBER IN  C.
  1689. ; NOWEVER, IFF THE NUMBER OF DIGITS IS LARGER THAN THE NUMBER
  1690. ; IN C, ALL DIGITS ARE PRINTED ANYWAY. NEGATIVE SIGN IS  ALSO
  1691. ; PRINTED AND COUNTED IN, POSITIVE SIGN IS NOT.
  1692. ;
  1693. ; 'PRTLN' PRINTS A SAVED TEXT LINE WITH LINE # AND ALL.
  1694. ;
  1695. ;
  1696. ;
  1697. PRTSTG:
  1698.     MOV    CH,AL    ;****PRTSTG****
  1699. PS1:
  1700.     MOV    SI,DX
  1701.     LODB    ;GET A CHAR
  1702.     LAHF            ;PRESERVE FLAGS
  1703.     INC    DX
  1704.     SAHF            ;RESTORE FLAGS
  1705.     CMP    AL,CH    ;SAME AS OLD A?
  1706.     JNZ    PS2    ;YES, RETURN
  1707.         RET
  1708. PS2:    CALL    CHROUT    ;ELSE, PRINT IT
  1709.     CMP    AL,0DH    ;WAS IT A CR?
  1710.     JNZ    PS1    ;NO, NEXT
  1711.     RET
  1712.     ;
  1713. QTSTG:
  1714.     MOV    AH,'"'
  1715.     CALL    IGNBLNK
  1716.     JNZ    QT3
  1717.     MOV    AL,34    ;IT IS A '"'
  1718. QT1:
  1719.     CALL    PRTSTG    ;PRINT UNTIL ANOTHER
  1720.     CMP    AL,0DH    ;WAS LAST ONE A CR?
  1721.     POP    BX    ;RETURN ADDRESS
  1722.     JNZ    QT2    ;WAS CR, RUN NEXT LINE
  1723.         JMP     RUNNXL
  1724. QT2:
  1725.     INC    BX    ;SKIPS TWO BYTES ON RETURN!!!!
  1726.     INC    BX
  1727.     JMP    BX    ;JUMP TO ADDRESS IN BX
  1728. QT3:
  1729.     MOV    AH,39    ;IS IT A SINGLE QUOTE (')?
  1730.     CALL    IGNBLNK
  1731.     JNZ    QT4
  1732.     MOV    AL,39    ;YES, DO SAME
  1733.     JP    QT1    ;AS IN ' " '
  1734. QT4:
  1735.     MOV    AH,'\'
  1736.     CALL    IGNBLNK    ;IS IT BACK-SLASH?('\')
  1737.     JNZ    QT5
  1738.     MOV    AL,141    ;YES, 0DH WITHOUT LF!
  1739.     CALL    CHROUT    ;DO IT TWICE
  1740.     CALL    CHROUT    ;TO GIVE TTY ENOUGH TIME
  1741.     POP    BX    ;RETURN ADDRESS
  1742.     JP    QT2
  1743. QT5:
  1744.     RET        ;NONE OF THE ABOVE
  1745.     ;
  1746. ; ON ENTRY BX = BINARY #,CL = # SPACES
  1747. ;
  1748. PRTNUM:
  1749.     PUSH    DX    ;****PRTNUM****
  1750.     MOV    DX,10    ;DECIMAL
  1751.     PUSH    DX    ;SAVE AS A FLAG
  1752.     MOV    CH,DH    ;CH=SIGN
  1753.     DEC    CL    ;CL=SPACES
  1754.     CALL    CHKSGN    ;CHECK SIGN
  1755.     JNS    PN1    ;NO SIGN
  1756.     MOV    CH,45    ;CH=SIGN
  1757.     DEC    CL    ;'-' TAKES SPACE
  1758. PN1:
  1759.     PUSH    CX    ;SAVE SIGN % SPACE
  1760. PN2:
  1761.     CALL    DIVIDE    ;DIVIDE BX BY 10 (IN DX)
  1762.     OR    CX,CX    ;CX HAS QUOTIENT
  1763.     JZ    PN3    ;YES, WE GOT ALL
  1764.     POP    AX    ;GET SIGN AND SPACE COUNT
  1765.     PUSH    BX    ;SAVE REMAINDER
  1766.     DEC    AL    ;DEC SPACE COUNT
  1767.     PUSH    AX    ;SAVE NEW SIGN AND SPACE COUNT
  1768.     MOV    BX,CX    ;MOVE RESULT TO BX
  1769.     JP    PN2    ;AND DIVIDE BY 10
  1770. PN3:
  1771.     POP    CX    ;WE GOT ALL DIGITS IN
  1772. PN4:
  1773.     DEC    CL    ;THE STACK
  1774.     MOV    AL,CL    ;LOOK AT SPACE COUNT
  1775.     OR    AL,AL
  1776.     JS    PN5    ;NO LEADING BLANKS
  1777.     MOV    AL,32    ;LEADING BLANKS
  1778.     CALL    CHROUT
  1779.     JP    PN4
  1780. PN5:
  1781.     MOV    AL,CH    ;PRINT SIGN
  1782.     CALL    CHROUT    ;MAYBE, OR NULL
  1783.     MOV    DL,BL    ;LAST REMAINDER IN E
  1784. PN6:
  1785.     MOV    AL,DL    ;CHECK DIGIT IN E
  1786.     CMP    AL,10    ;10 IS FLAG FOR NO MORE
  1787.     POP    DX
  1788.     JZ    RET    ;IFF SO, RETURN
  1789.     ADD    AL,48    ;ELSE CONVERT TO ASCII
  1790.     CALL    CHROUT    ;AND PRINT THE DIGIT
  1791.     JP    PN6    ;GO BACK FOR MORE
  1792.     ;
  1793. PRTLN:
  1794.     MOV    SI,DX
  1795.     LODW
  1796.     MOV    BX,AX
  1797.     INC    DX
  1798.     INC    DX    ;MOVE POINTER
  1799. PRTLN1:    MOV    CL,5    ;PRINT 5 DIGIT LINE #
  1800.     CALL    PRTNUM
  1801.     MOV    AL,32    ;FOLLOWED BY A BLANK
  1802.     CALL    CHROUT
  1803.     SUB    AL,AL    ;AND THEN THE TEXT
  1804.     CALL    PRTSTG
  1805.     RET
  1806. ;
  1807. ;
  1808. ;
  1809. ; **** MVUP **** MVDOWN **** POPA **** PUSHA ****
  1810. ;
  1811. ; 'MVUP' MOVES A BLOCK UP FROM WHERE DX -> WHERE CX -> UNTIL
  1812. ; DX = BX
  1813. ;
  1814. ; 'MVDOWN' MOVES A BLOCK DOWN FROM WHERE DX -> TO WHERE BX->
  1815. ; UNTIL DX = CX.
  1816. ;
  1817. ; 'POPA' RESTORES THE 'FOR' LOOP VAR SAVE AREA FROM THE STACK.
  1818. ;
  1819. ; 'PUSHA' STACKS THE 'FOR' LOOP VARIABLE SAVE AREA IN THE STACK
  1820. ;
  1821. ;
  1822. MVUP:
  1823.     CMP    DX,BX    ;***MVUP***
  1824.     JZ    RET    ;DE = HL, RETURN
  1825.     MOV    SI,DX
  1826.     LODB    ;GET ONE BYTE
  1827.     MOV    DI,CX
  1828.     STOB    ;MOVE IT
  1829.     INC    DX
  1830.     INC    CX
  1831.     JP    MVUP    ;UNTIL DONE
  1832.     ;
  1833. MVDOWN:
  1834.     CMP    DX,CX
  1835.     JZ    RET    ;YES, RETURN
  1836. MD1:
  1837.     LAHF
  1838.     DEC    DX
  1839.     DEC    BX
  1840.     MOV    SI,DX
  1841.     LODB    ;BOTH POINTERS AND
  1842.     MOV    [BX],AL    ;THEN DO IT
  1843.     JP    MVDOWN    ;LOOP BACK
  1844.     ;
  1845. POPA:
  1846.     POP    CX    ;CX = RETURN ADDR
  1847.     POP    BX    ;RESTORE LOPVAR, BUT
  1848.     MOV    [LOPVAR],BX    ;=0 MEANS NO MORE
  1849.     OR    BX,BX
  1850.     JZ    PP1    ;YES, GO RETURN
  1851.     POP    BX    ;NO, RESTORE OTHERS
  1852.     MOV    [LOPINC],BX
  1853.     POP    BX
  1854.     MOV    [LOPLMT],BX
  1855.     POP    BX
  1856.     MOV    [LOPLN],BX
  1857.     POP    BX
  1858.     MOV    [LOPPT],BX
  1859. PP1:
  1860.     PUSH    CX    ;CX = RETURN ADDR
  1861.     RET
  1862.     ;
  1863. PUSHA:
  1864.     MOV    BX,STKLMT    ;****PUSHA****
  1865.     CALL    CHGSGN
  1866.     POP    CX    ;CX=RET ADDR
  1867.     ADD    BX,SP
  1868.     JC    PUSHB    ;YES, SORRY FOR THAT.
  1869.         JMP     QSORRY
  1870. PUSHB:    MOV    BX,[LOPVAR]    ;ELSE SAVE LOOP VARS
  1871.     OR    BX,BX    ;THAT WILL BE ALL
  1872.     JZ    PU1
  1873.     MOV    BX,[LOPPT]    ;ELSE, MORE TO SAVE
  1874.     PUSH    BX
  1875.     MOV    BX,[LOPLN]    ;ELSE, MORE TO SAVE
  1876.     PUSH    BX
  1877.     MOV    BX,[LOPLMT]
  1878.     PUSH    BX
  1879.     MOV    BX,[LOPINC]
  1880.     PUSH    BX
  1881.     MOV    BX,[LOPVAR]
  1882. PU1:
  1883.     PUSH    BX
  1884.     PUSH    CX    ;CX = RETURN ADDR
  1885.     RET
  1886.     ;
  1887.     ;
  1888.     ; **** OUTC **** CHKIO ****
  1889.     ;
  1890.     ;
  1891.     ; THESE ARE THE ONLY I/O ROUTINES IN TBI.
  1892.     ;
  1893.     ;
  1894.     ; 'CHKIO' CHECKS THE INPUT, IFF NO INPUT, IT WILL RETURN TO  THE
  1895.     ; CALLER WITH THE Z FLAG SET. IFF THERE IS INPUT, THE Z FLAG  IS
  1896.     ; CLEARED AND THE INPUT BYRE IS IN A. HOWEVER, IFF THE INPUT  IS
  1897.     ; A CONTROL-O, THE 'OCSW' IS COMPLIMENTED, AND THE Z FLAG IS RE-
  1898.     ; TURNED. IFF A CONTROL-C IS READ, 'CHKIO' WILL RESTART TBI  AND
  1899.     ; DOES NOT RETURN TO THE CALLER.
  1900.     ;
  1901. CRLF:    MOV    AL,0DH    ;****CRLF****
  1902. CHROUT:
  1903.     CMP    [OCSW],0
  1904.     JZ    COUT1    ;SEE IF OUTPUT REDIRECTED
  1905.     PUSH    CX    ;SAVE CX ON STACK
  1906.     PUSH    DX    ;AND DX
  1907.     PUSH    BX    ;AND BX TOO
  1908.     MOV    [OUTCAR],AL    ;SAVE CHATACTER
  1909.     MOV    DL,AL    ;PUT CHAR IN E FOR CP/M
  1910.     MOV    AH,CONOUT ;CONSOLE OUTPUT
  1911.     INT    33    ;CALL MS-DOS AND OUTPUT CHAR
  1912.     MOV    AL,[OUTCAR]    ;GET CHAR. BACK
  1913.     CMP    AL,0DH    ;WAS IT A 'CR'?
  1914.     JNZ    DONE    ;NO,DONE
  1915.     MOV    DL,0AH    ;GET LINEFEED
  1916.     MOV    AH,CONOUT ;CONSOLE OUTPUT AGAIN
  1917.     INT    33    ;CALL MS-DOS
  1918. DONE:
  1919.     MOV    AL,[OUTCAR]    ;GET CHAR BACK
  1920. IDONE:
  1921.     POP    BX    ;GET H BACK
  1922.     POP    DX    ;AND D
  1923.     POP    CX    ;THEN H
  1924.     RET    ;DONE AT LAST
  1925. COUT1:
  1926.     CMP    B,AL,0    ;IS IT NULL?
  1927.     JZ    RET    ;SKIP IT
  1928.     STOB        ;STORE AL (CHAR) IN BUFFER
  1929.     INC    [BUFFER-1] ;INCREMENT COUNTER
  1930.     RET        ;DONE
  1931. CHKIO:
  1932.     PUSH    CX    ;SAVE B ON STACK
  1933.     PUSH    DX    ;AND D
  1934.     PUSH    BX    ;THEN H
  1935.     MOV    AH,CONST ;GET CONSOLE STATUS WORD
  1936.     INT    33    ;CALL MS-DOS
  1937.     OR    AL,AL    ;SET FLAGS
  1938.     JNZ    CI1    ;IF READY, GET CHAR
  1939.     JP    IDONE    ;RESTORE AND RETURN
  1940. CI1:
  1941.     MOV    AH,1    ;CALL THE BDOS
  1942.     INT    33    ;CALL MS-DOS
  1943. CI2:
  1944.     CMP    AL,18H    ;IS TI CONTROL-X?
  1945.     JNZ    IDONE    ;RETURN AND RESTORE IF NOT
  1946.     JMP    RSTART    ;YES, RESTART TBI
  1947. LSTROM:    EQU    $    ;ALL ABOVE CAN BE ROM
  1948. OUTIO:
  1949.     OUTB    0FFH
  1950.     RET
  1951. WAITIO:
  1952.     INB    0FFH
  1953.     XOR    AL,BH
  1954.     AND    AL,BL
  1955.     JZ    WAITIO
  1956.     CALL    FINISH
  1957. INPIO:
  1958.     INB    0FFH
  1959.     MOV    BL,AL
  1960.     RET
  1961.     ;
  1962. ;
  1963. ; IGNBLNK
  1964. ;
  1965. ;    DEBLANKS WHERE DX->
  1966. ;    IF (DX)=AH THEN DX:=DX+1
  1967. ;
  1968. IGNBLNK:MOV    SI,DX
  1969. IGN1:   LODB            ;GET CHAR IN AL
  1970.     CMP    AL,32    ;IGNORE BLANKS
  1971.     JNZ    IGN2    ;IN TEXT (WHERE DX ->)
  1972.         INC     DX
  1973.         JP      IGN1
  1974. IGN2:    CMP    AL,AH    ;IS SEARCH CHARACTER FOUND AT (DX)?
  1975.     JNZ    RET    ;NO, RETURN, POINTER (DX) STAYS
  1976.     LAHF        ;SAVE RESULTS OF COMPARISON
  1977.     INC    DX    ;INC POINTER IF CHARACTER MATCHES
  1978.     SAHF        ;RETURN RESULT OF COMPARISON TO FLAGS
  1979.     RET
  1980.     ;
  1981. FINISH:    POP    AX
  1982.     CALL    FIN    ;CHECK END OF COMMAND
  1983.     JMP    QWHAT    ;PRINT "WHAT?" IFF WRONG
  1984.     ;
  1985. OUTCAR:
  1986.     DB    0    ;OUTPUT CHAR STORAGE
  1987. OCSW:
  1988.     DB    0FFH    ;OUTPUT SWITCH
  1989. CURRNT:
  1990.     DW    0    ;POINTS TO CURRENT LINE
  1991. STKGOS:
  1992.     DW    0    ;SAVES SP IN 'GOSUB'
  1993. VARNXT:
  1994.     DW    0    ;TEMP STORAGE
  1995. STKINP:
  1996.     DW    0    ;SAVES SP IN 'INPUT'
  1997. LOPVAR:
  1998.     DW    0    ;'FOR' LOOP SAVE AREA
  1999. LOPINC:
  2000.     DW    0    ;INCREMENT
  2001. LOPLMT:
  2002.     DW    0    ;LIMIT
  2003. LOPLN:
  2004.     DW    0    ;LINE NUMBER
  2005. LOPPT:
  2006.     DW    0    ;TEST POINTER
  2007. RANPNT:
  2008.     DW    0    ;RANDOM NUMBER POINTER
  2009. TXTUNF:
  2010.     DW    TXTBGN    ;-> UNFILLED TEXT AREA
  2011. TXTBGN:    DS    1
  2012. MSG1:    DB    '8086 TINY BASIC V1.1 27 JUNE 82',0DH
  2013.     ORG    2000H    ;MISC STORAGE, INCLUDING STACK
  2014. TXTEND:    EQU    $    ;TEST AREA SAVE AREA ENDS
  2015. VARBGN:
  2016.     DS    54    ;VARIABLE @(0)
  2017.     DB    80    ;MAX CHARS IN BUFFER
  2018.     DB    0    ;CHAR COUNT
  2019. BUFFER:
  2020.     DS    80    ;BUFFER MUST BE AFTER TEXT AREA
  2021. BUFEND:    EQU    $
  2022.     DS    400    ;EXTRA BYTES FOR STACK
  2023. STKLMT:    DS    100    ;TOP LIMIT FOR STACK
  2024. STACK:    EQU    $    ;STACK STARTS HERE
  2025.     END    
  2026. ə